调用可变参数宏M
并且其variadic参数没有参数是否合法?
相关标准报价为 [cpp.replace] / 4 :
如果宏定义中的标识符列表没有以省略号结尾,则在调用类函数宏时,参数的数量(包括那些不包含预处理标记的参数)应等于参数的数量。宏定义。否则,调用中的参数应该多于宏定义中的参数(
...
除外)。应该存在一个)
预处理标记来终止调用。
对于没有非可变参数的情况,M()
形式的调用应该是合法的,因为调用有一个参数(由没有预处理标记组成)。因此,除了非变量参数之外还有一个参数。
对于具有一个非变量参数的情况,是否应该在,
中有一个尾随M(1,)
来引入一个参数,该参数不包含变量参数的预处理标记?否则,参数的数量将等于非可变参数的数量。即,
#define variadic(x,...) #__VA_ARGS__
variadic(1,) // 2 arguments: ok
variadic(1) // 1 argument: wrong?
然而, Clang 和 GCC 都接受以下测试用例:
#include <iostream>
#define variadic(x,...) #__VA_ARGS__
int main()
{
std::cout << "'" variadic(1) "'" << std::endl;
}
并产生输出:
''
这是非标准行为吗?
答案 0 :(得分:5)
否则,调用中的参数应该多于宏定义中的参数(不包括...)。
标准的这一摘录表明您的代码无效:您有一个参数加上省略号。如果我们遵循上述标准的部分,您应该至少有两个参数。当您编写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;
GCC也发出警告:
main.cpp:7:32: warning: ISO C99 requires rest arguments to be used [enabled by default]
std::cout << "'" variadic(1) "'" << std::endl;
因为这对程序员来说可能很麻烦,而且由于程序员的意图很容易猜到,所以他们都认为variadic(1)
等同于variadic(1,)
。