在变量宏扩展中我的逗号在哪里消失?
Where do my commas disappear in variadic macro expansion?
我正在为我的一个项目编写一个基于x-macro 的寄存器文件布局描述系统。大多数时候,宏会扩展到模板 类 的层次结构。但是,我还想要所有寄存器的枚举,如下所示:
#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
,然后单独得到参数 ""
。
我正在为我的一个项目编写一个基于x-macro 的寄存器文件布局描述系统。大多数时候,宏会扩展到模板 类 的层次结构。但是,我还想要所有寄存器的枚举,如下所示:
#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
,然后单独得到参数 ""
。