除非前面有命名参数,否则为什么可变参数宏在“)”标记之前会因预期的主表达式而失败?
Why does variadic macro fail with expected primary-expression before ‘)’ token unless preceded by a named argument?
我正在尝试创建一些使用可变参数的跟踪宏。只有当命名参数位于可变参数之前时,宏似乎才能正常运行。
我正在做的事情的最小代码版本如下所示。只有不带参数的 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__
预处理器标记,可用于以可移植的方式执行此操作:
#define TraceTest(...) f("Trace Start " __VA_OPT__(,) __VA_ARGS__)
只有当 __VA_ARGS__
不为空时 __VA_OPT__
才会被其参数替换,因此 TraceTest()
将被替换为 f("Trace Start ")
.
我正在尝试创建一些使用可变参数的跟踪宏。只有当命名参数位于可变参数之前时,宏似乎才能正常运行。
我正在做的事情的最小代码版本如下所示。只有不带参数的 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__
预处理器标记,可用于以可移植的方式执行此操作:
#define TraceTest(...) f("Trace Start " __VA_OPT__(,) __VA_ARGS__)
只有当 __VA_ARGS__
不为空时 __VA_OPT__
才会被其参数替换,因此 TraceTest()
将被替换为 f("Trace Start ")
.