Where do my commas disappear in variadic macro expansion?

时间:2016-10-19 13:41:54

标签: c++ c++11 c-preprocessor x-macros

I am writing a x-macro based register file layout description system for a project of mine. Most of the time, the macros expand to a hierarchy of template classes. However, I also want an enumeration of all the registers, like this:

#define RINT(num,name,flags,width) name,
...

enum Regs
{
#include REGDEF
};

This works just fine. However, I also specify aliasing registers using a variadic macro. Since there is no trivial way to strip commas between elements of __VA_ARGS__ (not that I know of, please correct me if I'm wrong), I write:

#define RALIAS_10(r0,r1,r2,r3,r4,r5,r6,r7,r8,r9) r0 r1 r2 r3 r4 r5 r6 r7 r8 r9
#define RALIAS_9(r0,r1,r2,r3,r4,r5,r6,r7,r8) r0 r1 r2 r3 r4 r5 r6 r7 r8
...
#define RALIAS_1(r0) r0
#define RALIAS_N(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,aliasn,...) aliasn
#define RALIAS(...) RALIAS_N(__VA_ARGS__, RALIAS_10(__VA_ARGS__), RALIAS_9(__VA_ARGS__), ..., RALIAS_1(__VA_ARGS__))

Now, if I write

RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

the commas in the RINT macro disappear:

enum Reg
{
...
RSP ESP SP SPL
...
};

If, in turn, I use the RALIAS_4 macro directly

RALIAS_4(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

I get what I expect:

enum Reg
{
...
RSP, ESP, SP, SPL,
...
};

I know GCC applies some non-standard comma stripping logic to variadic macros, but that shouldn't happen when I explicitly specify -std=c++11. Furthermore, Clang gave me the exact same results. Yet I couldn't find anything that would explain this behavior in the standard (draft), nor in the GCC documentation.

What am I missing?

I tried GCC 6.1.1 and Clang 3.8.1 on Arch Linux (x86-64). Both compilers were installed from the repository.

1 个答案:

答案 0 :(得分:2)

此:

RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

将扩展为:

RALIAS(RSP,,ESP,,SP,,SPL,)

这是一个带有8个参数的宏,其中4个为空。您没有获得参数"RSP,",您获得参数RSP,然后单独参数""