可变参数宏,其可变参数没有参数

Variadic macro with no arguments for its variadic parameter

本文关键字:参数 变参      更新时间:2023-10-16

是否合法调用一个可变宏M没有参数为其可变参数?

相关标准报价为[cpp.replace]/4:

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

对于没有非可变参数的情况,M()形式的调用应该是合法的,因为调用只有一个参数(不包含预处理令牌)。这样就比非可变形参多了一个实参

对于只有一个非可变参数的情况,是否应该像M(1,)一样在后面加上,来为可变参数引入一个不包含预处理令牌的参数?否则,实参的数量将等于非可变形参的数量。例如,

#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;
}

和产生作为输出:

''

这是不标准的行为吗?

否则,调用中的实参将多于宏定义中的形参(不包括…)。

这个从标准中提取的部分表明你的代码不应该是有效的:你有一个参数加上省略号。如果我们遵循上面的标准部分,您应该至少有两个参数。当你写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,)