Variadic宏,其variadic参数没有参数

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)

但是,ClangGCC都接受以下测试用例:

#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)

这是非标准行为吗?

Mor*_*enn 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;
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,).

  • 更改`#define variadic(x,...)#__ VA_ARGS__`→`#define variadic(...)#__ VA_ARGS__`是否足够?(示例摘自OP的帖子) (2认同)