Variadic宏,其variadic参数没有参数

时间:2013-05-27 07:01:03

标签: c++ c++11 c-preprocessor language-lawyer variadic-macros

调用可变参数宏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;
}

并产生输出:

''

这是非标准行为吗?

1 个答案:

答案 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,)