类似函数的宏从括号模板参数列表中"steal"逗号是否合法?

Is it legal for a function-like macro to "steal" commas from a parenthesized template argument list?

本文关键字:steal 是否 列表 函数 参数      更新时间:2023-10-16

我只是感到惊讶,为类函数的宏提供带有两个模板参数的类型会导致编译器报错。

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

template<typename T>    struct foo{};
template<typename T, U> struct bar{};
#define p(x) printf("sizeof(" #x ") = %un", 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段)规定了最外层的圆括号分隔有界的令牌序列。单词"最外层"表明可能还存在预处理器识别的其他(非最外层)括号。
此外,它显式地声明"跳过中间匹配的左括号和右括号"以及"匹配的内括号之间的逗号预处理标记不会分开参数"——这意味着如果我阅读正确,那么至少最后一行应该在我的理解中通过。

我理解错了什么?

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

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

可变宏(c++ 11)在这里作为一种替代方法工作得很好。

#define p(...) printf("sizeof(" #__VA_ARGS__ ") = %un", sizeof(__VA_ARGS__));