13

调用M不带可变参数的可变参数宏是否合法?

相关的标准报价是[cpp.replace]/4

如果宏定义中的标识符列表不以省略号结尾,则调用类函数宏时的参数数量(包括那些不包含预处理标记的参数)应等于宏定义中的参数数量。否则,调用中的参数应多于宏定义中的参数(不包括...)。应该存在)终止调用的预处理令牌。

对于没有非可变参数的情况,表单中的调用M()应该是合法的,因为调用有一个参数(不包含预处理标记)。所以比非可变参数多了一个参数。

对于具有一个非可变参数的情况,是否应该有一个尾随,M(1,)引入一个不包含可变参数的预处理标记的参数?否则,参数的数量将等于非可变参数的数量。IE,

#define variadic(x,...) #__VA_ARGS__

variadic(1,) // 2 arguments: ok
variadic(1) // 1 argument: wrong?

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

#include <iostream>

#define variadic(x,...) #__VA_ARGS__

int main()
{
    std::cout << "'" variadic(1) "'" << std::endl;
}

并产生输出:

''

这是非标准行为吗?

4

1 回答 1

8

否则,调用中的参数应该多于宏定义中的参数(不包括...)。

标准中的这一非常摘录表明您的代码不应该是有效的:您有一个参数加上省略号。如果我们遵循上述标准的部分,您应该至少有两个参数。当您编写 时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,).

于 2013-05-27T08:30:23.977 回答