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



考虑最小的例子:

template <int>
struct bar { };
int main() 
{
[](auto i) -> bar<i> { return {}; };
}

甚至:

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

Clang编译这两种形式没有问题,但GCC发现用法无效(例1),(例2)

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

这似乎是一个gcc错误。我将其报告为问题#80242


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

错误:模板参数 1 无效


我遵循了从trailing-return-typetemplate-argument的C++语法,这需要是一个constant-expression

模板参数

  • 常量表达式<->
  • 类型 ID
  • 身份表达式

那么真正的问题变成了:"i是一个有效的constant-expression吗?

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

类型为T的转换常量表达式是

隐式转换为类型T的表达式,其中转换后的表达式是常量表达式,隐式转换序列仅包含:

  • 用户定义的转换,

[...]

(注意:此类表达式可用于新表达式、大小写表达式、枚举器初始值设定项(如果基础类型是固定的)、数组边界和非类型模板参数

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

template <int>
struct bar { };
template <class I>
auto foo(I i) -> bar<i> { }
int main()
{
foo(std::integral_constant<int, 1>{}); // (0)
}
  • (0)处的函数调用上下文中,参数istd::integral_constant<int, 1>的实例。

  • std::integral_constant提供对基础value_typeconstexpr用户定义转换。

  • 转换
  • 后的常量表达式明确允许用户定义的转换,如上文§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 是核心常量表达式 除非评估E,遵循摘要的规则 机器 (1.9),将计算以下表达式之一:j

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

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

在CLANG和GCC中,如果您输入模板,您将根据上述措辞收到错误。我相信,由于在示例中没有模板是必需的,因此两个编译器都是正确的。

最新更新