c++ - 为什么可变参数宏在 ‘)’ 标记之前以预期的主表达式失败,除非前面有命名参数?

标签 c++ macros g++ variadic-macros

我正在尝试创建一些使用可变参数的跟踪宏。只有当命名参数位于可变参数之前时,宏似乎才能正常运行。

我正在做的事情的最小代码版本如下所示。只有不带参数的 TraceTest() 失败。我还尝试创建一个中间宏,将一个虚拟的第一个参数传递给 TraceTest1,但也失败了。

template<typename ...Args>
inline void f(const char*, Args&&... args) { }

#define TraceTest1(a, args...) f("Trace Start ", ##args)
#define TraceTest(args...) f("Trace Start", ##args)

TraceTest();     // error: expected primary-expression before ‘)’ token
TraceTest("a");  // works
TraceTest1();    // works
TraceTest1("a"); // works

我已经阅读了有关可变参数宏的 gnu 文档,但找不到任何可以解释这一点的内容。

我在 Ubuntu 18.04 下使用 gcc 7.4.0 并编译

g++ -Wall -Wextra -std=c++17 src/event.cpp -obin/event

最佳答案

TraceTest() 扩展为 f("Trace start",),这显然是一个语法错误。

命名的可变宏参数和“,”的标记粘贴以及可变宏参数都不是标准的 C++(尽管我能找到的每个编译器都实现了后者)。如果您希望它们与 GCC 一起使用,请使用“-std=gnu++17”而不是“-std=c++17”。


请注意,C++20 正在添加一个新的 __VA_OPT__ 预处理器 token ,可用于以可移植的方式执行此操作:

#define TraceTest(...) f("Trace Start " __VA_OPT__(,) __VA_ARGS__)

Live Demo

仅当 __VA_ARGS__ 不为空时,

__VA_OPT__ 才会被其参数替换,因此 TraceTest() 将被替换为 f (“跟踪开始”)

关于c++ - 为什么可变参数宏在 ‘)’ 标记之前以预期的主表达式失败,除非前面有命名参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56370398/

相关文章:

c++ - 使用 MinGW 的非标准位置构建 Boost 1.52

c++ - Linux下使用distutils交叉编译python扩展

c++ - 如何提高素数生成器 (SPOJ) 解决方案的效率?

ios - 宏无法按Objective-C的要求工作

c - 使用不同的宏多次包含一个文件

macros - 可变递归预处理器宏 - 可能吗?

c++ - 错误使用 nullptr 的编译器错误

c++ - 使用 ctypes.cdll.LoadLibrary 从 Python 加载库时 ELF header 无效