圆括号使指针模板参数无效

Do parentheses make a pointer template argument invalid?

本文关键字:参数 无效 指针 圆括号      更新时间:2023-10-16

考虑以下代码:

int x = 0;
template<int& I>
struct SR {};
template<int* I>
struct SP {};
SR<(x)> sr;
SP<&(x)> sp;
int main(void)
{
}

clang++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标准中找不到任何能在这里产生影响的东西。此外,为什么引用大小写可以,但指针大小写不好?编译器拒绝程序是否正确?

我对该标准的理解是应该允许它,但我认为GCC和Clang的实现者不同意我的解释,他们可能是正确的。要得到明确的答案,最好询问std-discussion@isocpp.org邮件列表(我会给他们发一封电子邮件(。措辞可能有缺陷。

根据[temp.arg.notype],非类型模板参数的一种可能形式是:

一个常数表达式(5.19(,指定具有静态存储持续时间和外部或内部链接的完整对象的地址,或具有外部或内部连接的函数,包括函数templates和函数template-ids,但不包括非静态类成员,表示(忽略括号(为&id表达式,其中id表达式是对象或函数的名称,除了如果名称引用函数或数组,则可以省略&;如果对应的模板参数是一个参考。。。

这一切都取决于"忽略括号"的含义。GCC和Clang都接受(&x)而不接受&(x);他们似乎已经决定"忽略圆括号"的意思只是在外面,而不是在id表达式周围如果这是标准委员会的意图,则应澄清语言。

编辑:在C++17草案中,这是明确允许的,因为允许的非类型模板参数的形式已经大大放宽:

非类型的模板参数template自变量应为模版参数类型的转换常量表达式([expr.const](对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或对于指针类型,不应为的地址(:

  • 子对象([interro.object](
  • 临时对象([class.temporary](
  • 字符串文字([lex.string](
  • typeid表达式([expr.typeid](的结果,或
  • 预定义的CCD_ 7变量([dcl.fct.def.general](