C/C++ MACro/Template Blackmagic to Generate Unique Name

C/C++ macro/template blackmagic to generate unique name

If your compiler supports __COUNTER__ (it probably does), you could try:

// boiler-plate
#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __COUNTER__)

// per-transform type
#define GL_TRANSLATE_DETAIL(n, x, y, z) GlTranslate n(x, y, z)
#define GL_TRANSLATE(x, y, z) GL_TRANSLATE_DETAIL(MAKE_UNIQUE(_trans_), x, y, z)

For

{
GL_TRANSLATE(1.0, 0.0, 0.0);

// becomes something like:
GlTranslate _trans_1(1.0, 0.0, 0.0);

} // auto popmatrix

Looking for C/C++ pre-processor macro or template to reverse a hex macro array and generate hex number

If you remove { } you can just:

#define MY_ARRAY  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
#define DO_IT_2(_0,_1,_2,_3,_4,_5,_6,_7) (\
(unsigned long long)(_7) << (7 * 8) | \
(unsigned long long)(_6) << (6 * 8) | \
etc... \
(unsigned long long)(_0) << (0 * 8))
#define DO_IT(x) DO_IT_2(x)

update:

#define MY_ARRAY2 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
#define REVERSE_LL_8(_0,_1,_2,_3,_4,_5,_6,_7) (\
(unsigned long long)(_7) << (7 * 8) | \
(unsigned long long)(_6) << (6 * 8) | \
etc... \
(unsigned long long)(_0) << (0 * 8))
#define DO_IT_2(_0,_1,_2,_3,_4,_5,_6,_7,...) \
REVERSE_LL_8(_0,_1,_2,_3,_4,_5,_6,_7)
#define DO_IT(x) DO_IT_2(x)
#define DO_TOO_2(a0,a1,a2,a3,a4,a5,a6,a7,_0,_1,_2,_3,_4,_5,_6,_7) \
REVERSE_LL_8(_0,_1,_2,_3,_4,_5,_6,_7)
#define DO_TOO(x) DO_TOO_2(x)

DO_IT(MY_ARRAY2)
DO_TOO(MY_ARRAY2)

so I can use C++ features

In C++ it's a really simple contexpr function with initializer_list:

#include <initializer_list>
#define MY_ARRAY {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
constexpr unsigned long long DO_IT(const std::initializer_list<int>& l) {
unsigned long long r = 0;
for (auto&& i : l) {
r >>= 8;
r |= (unsigned long long)i << (7 * 8);
}
return r;
}
constexpr long a = DO_IT(MY_ARRAY);

Repeated Class Instantiation without using Identifier

See this answer

#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __LINE__)

MyClass MAKE_UNIQUE(name);
MyClass MAKE_UNIQUE(name);
...

Or just make an array:

MyClass arr[N];

Why these macros work
C11 standard, 6.10.3.1 Argument substitution:

After the arguments for the invocation of a function-like macro have been identified,
argument substitution takes place. A parameter in the replacement list, unless preceded
by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is
replaced by the corresponding argument after all macros contained therein have been
expanded. Before being substituted, each argument’s preprocessing tokens are
completely macro replaced as if they formed the rest of the preprocessing file; no other
preprocessing tokens are available.

Corresponding paragraph in C++ standard (16.3.1 Argument substitution) is exact copy of C standard's.

Better way to write an object generator for an RAII template class?

It seems pretty easy. The questioner himself proposed a nice solution, but he can just use a usual copy constructor with a const-reference parameter. Here is what i proposed in comments:

template<typename T, typename U, typename V>
class FooAdder
{
private:
mutable bool dismiss;
typedef OtherThing<T, U, V> Thing;
Thing &thing_;
int a_;
// many other members
public:
FooAdder(Thing &thing, int a);
FooAdder(FooAdder const&o);
~FooAdder();
FooAdder &foo(T t, U u);
FooAdder &bar(V v);
};

FooAdder::FooAdder(Thing &thing, int a)
:thing_(thing), a_(a), dismiss(false)
{ }

FooAdder::FooAdder(FooAdder const& o)
:dismiss(false), thing_(o.thing_), a_(o.a_)
{ o.dismiss = true; }

FooAdder::~FooAdder() {
if(!dismiss) { /* wrap up and call */ }
}

It Just Works.

template<typename T, typename U, typename V>
FooAdder<T, U, V>
AddFoo(OtherThing<T, U, V> &thing, int a)
{
return FooAdder<T, U, V>(thing, a);
}

int main() {
AddFoo(myThing, 2)
.foo(3, 4)
.foo(5, 6)
.bar(7)
.foo(8, 9);
}

No need for complex templates or smart pointers.

C++ preprocessor/macro to automatically add lines after function definition

A macro can only generate a consecutive block of text. It can't lay things out the way you show in the question.

However if you're willing to rearrange a little, it can be done.

#define UNIT_TEST_FUNCTION(function_name) \
void function_name(); // forward declaration \
int temp##function_name = register_function(#function_name, function_name); \
void function_name()

Does this mimic perfectly a function template specialization?

Chances are it will be optimized. But if you want to be sure you can use a compile-time if by using templates, e.g. Boost’s MPL if_ implementation.

Or you can use SFINAE (Boost.enable_if).

Template type deduction with a non-copyable class

Yes you can use the scope-guard technique

struct autolocker_base {
autolocker_base() { }
protected:
// ensure users can't copy-as it
autolocker_base(autolocker_base const&)
{ }

autolocker_base &operator=(autolocker_base const&)
{ return *this; }
};

template <T>
class autolocker : public autolocker_base {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}

autolocker(const autolocker& o)
:autolocker_base(o), lock(o.lock)
{ o.lock = 0; }

~autolocker() {
if(lock)
lock->unlock();
}

private:
autolocker& operator=(const autolocker&);

private:
mutable T *lock;
};

Then write a function creating the autolocker

template<typename T>
autolocker<T> makelocker(T *l) {
return autolocker<T>(l);
}

typedef autolocker_base const& autolocker_t;

You can then write it like this:

autolocker_t lock = makelocker(&my_lock);

Once the const reference goes out of scope, the destructor is called. It doesn't need to be virtual. At least GCC optimizes this quite well.

Sadly, this means you have to make your locker-object copyable since you need to return it from the maker function. But the old object won't try to unlock twice, because its pointer is set to 0 when it's copied, so it's safe.

C++ template black magic

Try typeid(Foo).name() for a start. Parse as you see fit; will be implementation-dependent (but simply getting a string back is portable).



Related Topics



Leave a reply



Submit