圆括号是否使指针模板参数无效?
考虑这个代码:
int x = 0;
template<int& I>
struct SR {};
template<int* I>
struct SP {};
SR<(x)> sr;
SP<&(x)> sp;
int main(void)
{
}
铿锵声++ 3.8.0抱怨:
main.cpp:10:5: error: non-type template argument does not refer to any declaration
SP<&(x)> sp;
^~~
main.cpp:6:15: note: template parameter is declared here
template<int* I>
^
g ++ 6.1.0抱怨:
main.cpp:10:8: error: template argument 1 is invalid
SP<&(x)> sp;
^
当然,如果我删除括号,一切正常,如SP<&x> sp;
。 但是我无法在C ++ 14 Standard中找到任何可以在这里发挥作用的东西。 此外,为什么参考案例好,但指针案件不好? 编译器是否正确拒绝该程序?
我对标准的阅读是应该允许的,但我认为GCC和Clang的实现者不同意我的解释,他们可能是正确的。 为了得到明确的答案,最好问问std-discussion@isocpp.org邮件列表(我会给他们发一封电子邮件)。 措辞可能是一个缺陷。
根据[temp.arg.nontype],非类型模板参数的可能形式之一是:
...一个常量表达式(5.19),指定具有静态存储持续时间和外部或内部链接的完整对象的地址,或者具有外部或内部链接的函数,包括函数模板和函数模板id,但不包括非静态类成员表示(忽略括号内)作为&
ID表达,其中的ID-expression是对象或函数的名称,除了&
如果名称是指功能或阵列,并且如果相应的模板将被省略,可以省略 - 参数是一个参考...
这一切都取决于“忽略括号”的含义。 GCC和Clang都接受(&x)
但不接受&(x)
; 他们似乎已经决定“忽略括号”仅仅意味着在外面,而不是围绕id表达。 如果这是标准委员会的意图,则应该澄清该语言。
编辑:在C ++ 17草案中,这是明确允许的,因为可允许的非类型模板参数的形式已大大放宽:
非类型模板参数的模板参数应该是模板参数类型的转换常量表达式([expr.const])。 对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或者对于指针类型,不应该是地址):
typeid
表达式的结果([expr.typeid])或 __func__
变量([dcl.fct.def.general])。 上一篇: Do parentheses make a pointer template argument invalid?