Variadic宏参数计数不能按预期工作

时间:2017-08-20 22:11:10

标签: c++ visual-c++ macros variadic-macros

所以,基本上我试图实现一个宏来计算 VA_ARGS 中的参数数量。

为简单起见,它最多只能工作3个参数。问题是当宏使用少于3个参数时,它不起作用,并触发"期望表达式"错误。

#define EXPAND( x ) x
#define PP_NARG(...) EXPAND(PP_ARG_N(__VA_ARGS__, PP_RSEQ_N()))
#define PP_ARG_N(_1, _2, _3, N,...) N
#define PP_RSEQ_N() 3,2,1,0

void main()
{
    printf("\nTEST PP_NARG: %i", PP_NARG());        //Doesn't work (in this case it shouldn't work, so it's correct)
    printf("\nTEST PP_NARG: %i", PP_NARG(0));       //Doesn't work
    printf("\nTEST PP_NARG: %i", PP_NARG(0,0));     //Doesn't work
    printf("\nTEST PP_NARG: %i", PP_NARG(0,0,0));   //Works
}

保持正常工作的线路正确编译并打印" TEST PP_NARG:3"。

我认为问题可能是PP_RSEQ_N()只扩展到" 3"而不是" 3,2,1,0"由于某种原因,因为即使PP_RSEQ_N()被定义为此

#define PP_RSEQ_N() 10,9,8,7,6,5,4,3,2,1,0

它仍然不能使用少于3个参数。

我正在使用MSVC编译器,它可能是问题的原因,因为它对宏的表现不是很好,如下所示:MSVC doesn't expand __VA_ARGS__ correctly

2 个答案:

答案 0 :(得分:2)

在您的实施中,PP_RSEQ_N()PP_ARG_N的参数。作为一个参数,它仅在预处理的参数替换阶段进行扩展,但这只发生在替换替换列表中的参数之前(只要在替换列表中,它不是字符串化并且没有参与粘贴。)

由于PP_ARG_N在其替换列表中只有第四个参数NPP_RSEQ_N()只会在您碰巧传入三个参数时才会展开。(在<期间有第二次扫描) em>重新扫描和替换阶段,适用于参数替换后...但这在调用中没有提及PP_RSEQ_N()

摆脱这个宏,只需将它放在PP_NARG中就像这样:

#define EXPAND( x ) x
#define PP_NARG(...) EXPAND(PP_ARG_N(__VA_ARGS__, 3,2,1,0))
#define PP_ARG_N(_1, _2, _3, N,...) N

......事情“工作正常”:

PP_NARG()扩展为1
PP_NARG(x)扩展为1
PP_NARG(x,y)扩展为2

但请注意,PP_NARG()不会给你0.可以说这实际上是正确的;到预处理器,这不传递零参数。它正在传递一个只是空的参数。与#define X(A) OPEN A CLOSE / X()产生OPEN CLOSE的情况相同。如果出于某种原因你想要将它扩展为0,那么可能需要一些努力来实现这一点,但对于这个答案,我只专注于让你超越这一个驼峰。

答案 1 :(得分:0)

here 中可以找到一个 PP_ARG_N() 实现,它也可以区分带参数和不带参数的调用(感谢 Scott Morrison)。对您的小程序的回应:

TEST PP_NARG: 0
TEST PP_NARG: 1
TEST PP_NARG: 2
TEST PP_NARG: 3