【问题标题】:Do parentheses make a pointer template argument invalid?括号是否使指针模板参数无效?
【发布时间】:2023-04-10 03:27:01
【问题描述】:

考虑这段代码:

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&lt;&amp;x&gt; sp;。但是我在 C++14 标准中找不到任何可以在这里有所作为的东西。此外,为什么参考案例可以,但指针案例不好?编译器是否正确拒绝程序?

【问题讨论】:

  • @LightnessRacesinOrbit:这个:&(std::cout)-as-template-argument
  • 对不起,是的。我想出了一个新的更直接的问题,即为什么是有序的,因为旧问题中如何解决的答案只是“删除括号”。
  • 我猜这与在对象名称周围添加括号会使表达式产生右值而不是左值这一事实有关。
  • @LightnessRacesinOrbit 我不确定那里的答案是否能回答问题。它链接到一个专门关于指向成员的指针的问题,但std::cout 是一个对象。
  • @templatetypedef 如果这么简单,你就做不到int f(int&amp;); int x; int y = f((x));

标签: c++ templates language-lawyer


【解决方案1】:

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

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

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

这一切都取决于“忽略括号”的含义。 GCC 和 Clang 都接受 (&amp;x) 但不接受 &amp;(x);他们似乎已经决定“忽略括号”仅表示在外部,而不是在 id-expression 周围。如果这是标准委员会的意图,则应该澄清语言。

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

非类型模板参数模板参数应该是类型的转换常量表达式([expr.const])模板参数。 对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或对于指针类型,不应是地址):

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

【讨论】:

  • 嗯。 N4296 不接近 C++14 吗?在 N4296 中,[temp.arg.nontype] 基本上只是遵循“转换后的常量表达式”,但有一些限制。
  • @aschepler 我认为 N4296 是 C++14 后的工作草案之一。另请参阅我的答案的编辑:我认为您看到的措辞是 C++17。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 2015-09-07
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
相关资源
最近更新 更多