条件表达式中的右值引用

Rvalue references in a conditional expression

本文关键字:引用 表达式 条件      更新时间:2023-10-16
typedef decltype(true ? (long&&)0 : (long&&)0) T;

T 应该是什么?

根据 gcc (4.7),它是long .根据叮当(树干)的说法,这是long&&.这种差异导致 clang 无法编译使用 gcc 4.7 的 libstdc++ 的代码。谁是对的?

更新:正如ildjarn指出的那样,Clang是对的,正如Richard Smith指出的那样,libstdc++错误是由于标准中的错误造成的。以下是相关的 GCC 错误,以及相关的缺陷报告。

Clang 是对的。N3337 §7.1.6.2/4:

decltype(e)表示的类型定义如下:

  • 如果e是无括号的 ID 表达式或无括号的类成员访问,则decltype(e)e 命名的实体的类型。如果没有这样的实体,或者如果e命名一组重载函数,则程序格式不正确;
  • 否则,如果e是x值,则decltype(e) T&&,其中Te的类型;
  • 否则,如果e是左值,则decltype(e) T&,其中Te的类型;
  • 否则,decltype(e)e的类型。

decltype说明符的操作数是未计算的操作数。

§5/6:

[ 注意:如果表达式是

    调用
  • 函数的结果,无论是隐式还是显式调用,其返回类型是对对象类型的右值引用,
  • 强制转换为对对象类型的右值引用
  • 类成员访问表达式,
  • 该表达式指定非引用类型的非静态数据成员,其中对象表达式是 x值,或
  • 一个指向成员.*指针表达式,其中第一个操作数是 x值,第二个操作数是指向数据成员的指针。
通常,此规则的效果是,命名的右值引用被视为左值,对对象的未命名右值引用

被视为 x值;对函数的右值引用被视为左值,无论是否命名。

我之前很谨慎,文字0可能会以某种方式阻止它在这种情况下成为对象类型,但 §3.9/8 澄清了事情:

对象类型是(可能符合 cv 条件的)类型,它不是函数类型、不是引用类型,也不是 void 类型。

条件运算符不影响此处的任何内容 – §5.16/4:

如果第二个和第三个操作数是相同值类别的 glvalue 并且具有相同的类型,则结果属于该类型和值类别,如果第二个或第三个操作数是位字段,或者如果两者都是位字段,则结果为位字段。

在这种情况下,两者具有相同的值类别 (xvalue),并且 x 值是 glvalues。