为什么我的可变参数宏不能正确接受任何参数?
Why won't my variadic macro accept no arguments correctly?
在参数数上重载宏
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++选择后一种解释(另一个答案引用了其文档)是合理和适当的,但如果您希望代码是可移植的,那么依赖它是不安全的。采用替代解释的编译器会有不同的行为,可能是提供了您期望的行为,也可能是拒绝了代码。
- 用于检查值是否为其任何参数的帮助程序函数
- C++ - 声明指向返回任何类型并获取任意数量参数的函数的指针
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- MSVC 错误:4 个重载中的任何一个都无法转换所有参数类型
- boost::p rogram_options 在指定意外的位置参数时不报告任何错误
- 使用聚合初始化模拟默认函数参数是否存在任何陷阱?
- 在将匿名对象作为参数传递时,不会调用任何构造函数
- 此函数如何在不传递任何参数的情况下工作?
- 高效的可变参数等于任何函数
- 如何声明一个接受任何大小的 2D 矢量参数?
- 如何在C++中接收任何类型的函数参数并获取函数内传递变量的类型?
- 在参数相关查找之前进行模板替换的任何方法(或解决方法?
- 部分专用化不使用其任何模板参数
- 创建一个构造函数,即Capabe获取任何数量的参数
- C++任何非类型参数的模板专用化
- 有没有办法跟踪任何编译器的模板参数推导?
- C 模板功能是否有任何方法可以采用n个参数
- 类介绍 (c++) 项目希望我们创建两个构造函数,但它们都不需要任何参数 - 我应该在这里做什么?
- 创建带有任何参数的 std::functions 的unordered_map?
- 将任何数据类型/对象作为参数传递以确定其大小