K-b*_*llo 8 c++ language-lawyer c-preprocessor variadic-macros c++11
调用M其可变参数的参数没有参数的可变参数宏是否合法?
相关标准报价为[cpp.replace]/4:
如果宏定义中的标识符列表不以省略号结尾,则在调用类函数宏时,参数的数量(包括那些不包含预处理标记的参数)应等于宏定义中的参数数量.否则,调用中的参数应该多于宏定义中的参数(不包括
...).应该存在一个)终止调用的预处理标记.
对于没有非可变参数的情况,表单中的调用M()应该是合法的,因为调用有一个参数(不包含预处理标记).因此,除了非变量参数之外还有一个参数.
对于具有一个非可变参数的情况,是否应该有一个尾随,,M(1,)以引入一个由variadic参数组成的参数?否则,参数的数量将等于非可变参数的数量.即
#define variadic(x,...) #__VA_ARGS__
variadic(1,) // 2 arguments: ok
variadic(1) // 1 argument: wrong?
Run Code Online (Sandbox Code Playgroud)
但是,Clang和GCC都接受以下测试用例:
#include <iostream>
#define variadic(x,...) #__VA_ARGS__
int main()
{
std::cout << "'" variadic(1) "'" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
并作为输出产生:
''
Run Code Online (Sandbox Code Playgroud)
这是非标准行为吗?
否则,调用中的参数应该多于宏定义中的参数(不包括...).
这个标准的摘录表明你的代码不应该是有效的:你有一个参数加上省略号.如果我们遵循上述标准的部分,您应该至少有两个参数.写作时varidadic(1),你只需提供一个参数.您的代码无效.
顺便说一句,clang发出警告:
main.cpp:7:32: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu]
std::cout << "'" variadic(1) "'" << std::endl;
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会也发出警告:
main.cpp:7:32: warning: ISO C99 requires rest arguments to be used [enabled by default]
std::cout << "'" variadic(1) "'" << std::endl;
Run Code Online (Sandbox Code Playgroud)
因为这对程序员来说可能很麻烦,而且由于程序员的意图很容易猜到,所以他们都认为variadic(1)是等同于variadic(1,).