圆括号使指针模板参数无效
Do parentheses make a pointer template argument invalid?
考虑以下代码:
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](
- std::cin >>上的参数无效
- 结果失败或多个参数无效
- 错误:一元"*"的类型参数无效(具有"int"):使用 mergesort 计算
- 错误 带有模块的一元"*"(具有"int")的类型参数无效
- 由于调用 std::condition_variable 后参数无效而导致应用程序崩溃
- MPI_Iprobe:RMA 调用中的位移参数无效
- 推力::sort_by_key上的配置参数无效
- windres 致命错误:将输出写入时:参数无效
- 一元'*'的类型参数无效(有双精度)
- C++:传递给 C 运行时函数的参数无效
- 矢量模板参数无效
- 写入 -: 参数无效 } 时出错
- winsock2:recvfrom()函数以错误10022(参数无效)结束
- 模板参数的显式指定参数无效,该参数是 constexpr
- 模板参数无效
- 调用 getter 成员时的参数无效
- 模板模板参数中的参数无效
- 方法调用中的参数无效
- POSIX 计时器:参数无效
- C++类模板是一个模板:模板参数无效