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方式推导出来的),在这种情况下,不要强迫它做一些变通方法直接访问它...
这似乎是一个gcc
错误.我把它报告为问题#80242.
gcc
抱怨i
作为模板参数的有效性:
错误:模板参数1无效
我已经按照C++语法从trailing-return-type
到template-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]中指定的任何规则.
因此,转换的常量表达式是常量表达式.
我相信你的两个例子都是错的.基于标准措辞5.20常量表达式[expr.const] /p2.7:
2条件表达式e是核心常量表达式,除非按照抽象机器(1.9)的规则评估e将评估以下表达式之一:j
...
- 左值 - 右值转换(4.1),除非它适用于:
函数参数不能是常量表达式,因为为了将它们作为模板参数传递,您将lvalue应用于它们的右值转换.
在CLANG和GCC中,如果你实例化模板,你将会根据上面的措辞得到一个错误.我相信,因为在示例中没有模板被实例化,所以不需要诊断,因此两个编译器都是正确的.
归档时间: |
|
查看次数: |
820 次 |
最近记录: |