可以在尾随返回类型语法中直接使用参数值(不是其类型而是值本身)

W.F*_*.F. 18 c++ language-lawyer c++11 trailing-return-type

考虑最小的例子:

template <int>
struct bar { };

int main() 
{
    [](auto i) -> bar<i> { return {}; };
}
Run Code Online (Sandbox Code Playgroud)

甚至:

template <int>
struct bar {};

template <class I>
auto foo(I i) -> bar<i> {}
Run Code Online (Sandbox Code Playgroud)

clang编译两种形式没有问题,但gcc发现使用无效(例如1),(例如2)

这个问题可能看起来很愚蠢,但是参数的类型可以让constexpr转换运算符重载(在这种情况下,i从传递给lambda/foo的值推导出的类型int是以constexpr方式推导出来的),在这种情况下,不要强迫它做一些变通方法直接访问它...

Vit*_*meo 6

这似乎是一个gcc错误.我把它报告为问题#80242.


gcc抱怨i作为模板参数的有效性:

错误:模板参数1无效


我已经按照C++语法trailing-return-typetemplate-argument,这需要一个constant-expression:

模板参数:

  • 常量表达式 < -
  • 类型ID
  • ID-表达

真正的问题就变成:"是i有效的constant-expression吗?" .

我认为答案是肯定的,因为§8.20.4 [expr.const]说:

转换常量表达式类型T是一个表达式,隐式转换为类型T,其中,所述转换后的表达式是一个常量表达式和隐式转换序列只包含:

  • 用户定义的转换,

[...]

(注意:这些表达式可以在新表达式中使用,作为case表达式,如果基础类型是固定的,则作为枚举器初始化器,作为数组边界,以及作为非类型模板参数.)

有一系列隐式转换,从开始i,将产生一个转换的常量表达式,它是一个常量表达式.鉴于:

template <int>
struct bar { };

template <class I>
auto foo(I i) -> bar<i> { }

int main()
{
    foo(std::integral_constant<int, 1>{}); // (0)
}
Run Code Online (Sandbox Code Playgroud)
  • (0)函数调用的上下文中,参数i是一个实例std::integral_constant<int, 1>.

  • std::integral_constant提供constexpr用户定义的底层转换value_type.

  • 转换的常量表达式明确允许用户定义的转换,如上面§8.20.4 [expr.const]所示.

  • std::integral_constant::operator value_type()将返回非类型模板参数1.这是一个核心常量表达式,因为它不违反§8.20.2 [expr.const]中指定的任何规则.

  • 因此,转换的常量表达式常量表达式.

  • 你仍然必须证明转换后的表达式是一个常量表达式,但我认为这基本上是正确的.一个例子也会有所帮助,因为这有点违反直觉. (2认同)

101*_*010 5

我相信你的两个例子都是错的.基于标准措辞5.20常量表达式[expr.const] /p2.7:

2条件表达式e是核心常量表达式,除非按照抽象机器(1.9)的规则评估e将评估以下表达式之一:j

...

- 左值 - 右值转换(4.1),除非它适用于:

函数参数不能是常量表达式,因为为了将它们作为模板参数传递,您将lvalue应用于它们的右值转换.

在CLANG和GCC中,如果你实例化模板,你将会根据上面的措辞得到一个错误.我相信,因为在示例中没有模板被实例化,所以不需要诊断,因此两个编译器都是正确的.