为什么我的可变参数宏不能正确接受任何参数?

Why won't my variadic macro accept no arguments correctly?

本文关键字:参数 任何 不能 我的 变参 为什么      更新时间:2023-10-16

在参数数上重载宏

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进行编译。

如果您能为我提供任何想法或其他资源,我们将不胜感激。

您可以在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__一起保留)。

C标准指定

如果宏定义中的标识符列表没有以省略号[…]结尾。否则,调用中的参数应多于宏定义中参数的数量(不包括…)

(C2011 6.10.3/4;增加强调)

C++11包含了与第16.3/4段具有相同效果的语言。

在这两种情况下,如果宏调用被解释为没有参数,那么程序将不一致。另一方面,预处理器确实识别并支持空的宏参数——也就是说,由零个预处理标记组成的参数。因此,原则上,无论证和单一空论证之间存在歧义,但在实践中,只有后一种解释才能产生一致的程序。

因此,g++选择后一种解释(另一个答案引用了其文档)是合理和适当的,但如果您希望代码是可移植的,那么依赖它是不安全的。采用替代解释的编译器会有不同的行为,可能是提供了您期望的行为,也可能是拒绝了代码。