C++ “宏”这样的函数是否合法;偷;括号内模板参数列表中的逗号?

C++ “宏”这样的函数是否合法;偷;括号内模板参数列表中的逗号?,c++,c-preprocessor,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>); // work

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

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

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;
}
模板结构foo{};
模板结构条{};
#定义p(x)printf(“sizeof(#x”)=%u\n,sizeof(x));
int main()
{
p(foo);//当然有效
p(bar);//不起作用
p((bar));//也不起作用
返回0;
}
使GCC(6.2.0)抱怨
宏“p”传递了2个参数,但只接受1个

当然,预处理器是一个预处理程序,它是文本替换,它不是真正的C++编译器,它理解模板或所有其他语言规则。 也许我要求的太多了,因为我希望预处理器能够识别尖括号,当然。。。但至少在规范中明确提到了括号

16.3(第10至12段)规定了限定标记有界序列的最外层括号。单词“最外层”表示预处理器可能还会识别出更多(而不是最外层)括号。
此外,它还明确指出“跳过中间匹配的左括号和右括号对”以及“匹配的内括号之间的逗号预处理标记分隔参数”-这意味着如果我阅读正确,那么至少我理解的最后一行应该通过

我理解错了什么?

p((bar))
是使用单个宏参数对
p
宏的有效调用,即
(bar)
。到目前为止,你的理解是正确的

不幸的是,它的扩展包括
sizeof((bar))
,并且
sizeof
不接受双括号类型

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

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

重新考虑一下宏执行纯文本处理,并检查它将扩展到什么。这就解释了,谢谢。可变宏确实有效。