A few months back Benjamin Stiglitz taught me that it’s finally possible to build practically-hygienic macros with modern plain ol’ C #defines. Here’s his example:
#define MIN_PASTE(A,B) A##B
#define MIN_IMPL(A,B,L) ({ \
__typeof__(A) MIN_PASTE(__a,L) = (A); \
__typeof__(B) MIN_PASTE(__b,L) = (B); \
MIN_PASTE(__a,L) < MIN_PASTE(__b,L) ? MIN_PASTE(__a,L) : MIN_PASTE(__b,L); \
})
#define MIN(A,B) MIN_IMPL(A,B,__COUNTER__)
So this C code:
int a = 11;
int b = 42;
int c = MIN(a, b);
preprocesses into this:
int a = 11;
int b = 42;
int c = ({
__typeof__(a) __a0 = (a);
__typeof__(b) __b0 = (b);
__a0 < __b0 ? __a0 : __b0;
});
Here’s how __COUNTER__ works:
A new predefined macro
__COUNTER__has been added. It expands to sequential integral values starting from 0. In conjunction with the ## operator, this provides a convenient means to generate unique identifiers.
It’s still not gensym-quality, since the generated variable name can shadow other variable names:
int a = 11;
int b = 42;
int __a0 = a * b; // uh oh
int c = MIN(a, b);
assert(__a0 == 462); // passes though
This is contrived, since you probably aren’t going to prefix your variable names with double-underscores. That said, this code does compile and execute correctly, although enabling -Wshadow will reveal all is not well.