对于类似函数的宏来说,偷窃"是否合法?括号模板参数列表中的逗号?

时间:2016-11-09 17:21:25

标签: c++ c-preprocessor

我很惊讶,为类似函数的宏提供一个带有两个模板参数的类型会导致编译器抱怨。

这个(概念上类似的)示例代码:

template<typename T>    struct foo{};
template<typename T, U> struct bar{};
#define p(x) printf("sizeof(" #x ") = %u\n", sizeof(x));

int main()
{
   p(foo<int>);        // works, of course
   p(bar<int,int>);    // does not work
   p((bar<int,int>));  // does not work either
   return 0;
}

让GCC(6.2.0)抱怨macro "p" passed 2 arguments, but takes just 1

当然,预处理器是一个预处理器进行文本替换,它不是真正的C ++编译器,它能理解模板或该语言的所有其他规则。

也许我通过期待预处理器识别尖括号而过多地要求,但是......但至少在规范中明确提到了括号。

16.3(第10至12段)规定了最外面的括号,用于界定有界的令牌序列。 &#34; outsidemost&#34; 这个词表明预处理器可能还有其他(不是最外面的)括号。
此外,它明确指出&#34;跳过中间匹配的左右括号对#34; 以及&#34;逗号预处理匹配内部括号之间的标记不要单独的参数&#34; - 这意味着如果我正确阅读,那么至少最后一行在我的理解中传递。

我理解错误是什么?

1 个答案:

答案 0 :(得分:6)

p((bar<int,int>))p宏的有效调用,具有单个宏参数,即(bar<int,int>)。到目前为止,您的理解是正确的。

不幸的是,它的扩展包括sizeof((bar<int,int>))sizeof不接受双重括号类型。

Variadic宏(C ++ 11)在这里可以很好地作为替代方案。

#define p(...) printf("sizeof(" #__VA_ARGS__ ") = %u\n", sizeof(__VA_ARGS__));