我正在为我的项目编写基于x宏的寄存器文件布局描述系统。大多数情况下,宏会扩展为模板类的层次结构。但是,我还希望对所有寄存器进行枚举,如下所示:

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

enum Regs
{
#include REGDEF
};

这样很好。但是,我也使用可变参数宏指定别名寄存器。由于没有简单的方法来剥离__VA_ARGS__元素之间的逗号(这不是我所知道的,如果我错了,请更正我),我这样写:
#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__))

现在,如果我写
RALIAS(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

RINT宏中的逗号消失:
enum Reg
{
...
RSP ESP SP SPL
...
};

反过来,如果我直接使用RALIAS_4宏
RALIAS_4(RINT(4, RSP, 0, 64), RINT(4, ESP, 0, 32), RINT(4, SP, 0, 16), RINT(4, SPL, 0, 8))

我得到了我所期望的:
enum Reg
{
...
RSP, ESP, SP, SPL,
...
};

我知道GCC对可变参数宏应用了一些非标准的逗号剥离逻辑,但是当我明确指定-std = c++ 11时,这应该不会发生。此外,Clang给了我完全相同的结果。但是我在标准(草稿)或GCC文档中都找不到能解释这种行为的东西。

我想念什么?

我在Arch Linux(x86-64)上尝试了GCC 6.1.1和Clang 3.8.1。这两个编译器都是从存储库安装的。

最佳答案

这个:

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参数,然后分别得到了""参数。

09-10 04:31