Overloading Macro on Number of Arguments
https://codecraft.co/2014/11/25/variadic-macros-tricks/
我一直在查看上面的两个链接,尝试使用以下代码:
#define _GET_NUMBER(_0, _1, _2, _3, _4, _5, NAME, ...) NAME
#define OUTPUT_ARGS_COUNT(...) _GET_NUMBER(_0, ##__VA_ARGS__, 5, 4, 3, 2, 1, 0)
...
cout << OUTPUT_ARGS_COUNT("HelloWorld", 1.2) << endl;
cout << OUTPUT_ARGS_COUNT("HelloWorld") << endl;
cout << OUTPUT_ARGS_COUNT() << endl;
编译,运行并提供以下输出:
2
1
1
我不能为我的生活弄清楚为什么调用OUTPUT_ARGS_COUNT()给我1而不是0.我对我正在尝试使用的代码有一个正确的理解,但它对我来说仍然有点希腊所以我猜我可能没有正确应用一些东西,尽管事实上我从堆栈溢出的链接中复制并粘贴了示例代码。
我正在使用g ++ 5.4.0 20160609进行编译。
非常感谢您指出的任何想法或其他资源。
答案 0 :(得分:2)
您可以在http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html看到:
其次,'##'标记粘贴运算符在逗号和变量参数之间具有特殊含义。如果你写
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
并且在使用eprintf宏时省略变量参数,然后将删除“##”之前的逗号。如果传递一个空参数,则不会发生这种情况,如果“##”前面的标记不是逗号,也不会发生这种情况。
eprintf ("success!\n")
→ fprintf(stderr, "success!\n");
上述解释对于唯一的宏参数是变量参数参数的情况是模棱两可的,因为尝试区分根本没有参数是空参数还是缺少参数是没有意义的。 CPP在符合特定C标准时保留逗号。否则,逗号将被删除作为标准的扩展名。
所以,(除非使用适当的扩展名)OUTPUT_ARGS_COUNT()
被计为1个空参数(逗号与##__VA_ARGS__
保持一致)。
答案 1 :(得分:2)
C标准指定
如果宏定义中的标识符列表没有以省略号结尾,[...]。否则, 调用中的参数应该多于宏定义中的参数(不包括...)
(C2011 6.10.3/4;重点补充)
C ++ 11包含与第16.3 / 4段中相同效果的语言。
在这两种情况下,如果您的宏调用被解释为零参数,那么您的程序将是不符合的。另一方面,预处理器确实识别并支持空的宏参数 - 即由零预处理标记组成的参数。原则上,这里没有论证和单个空论证之间存在歧义,但在实践中,只有后一种解释才会产生一致的程序。
g ++选择后一种解释(另一个答案引用其文档为此效果)是合理和合适的,但如果您希望您的代码可移植,依赖它是不安全的。采用替代解释的编译器可能会有不同的行为,可能是通过提供您期望的行为,但也可能通过拒绝代码。