条件表达式中的右值引用

HC4*_*ica 3 c++ gcc clang decltype c++11

typedef decltype(true ? (long&&)0 : (long&&)0) T;
Run Code Online (Sandbox Code Playgroud)

应该是什么?

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

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

ild*_*arn 5

Clang是对的.N3337§7.1.6.2/ 4:

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

  • if e是未加密码的id-expression或未加密码的类成员访问,decltype(e)是指定的实体的类型e.如果没有这样的实体,或者e命名一组重载函数,程序就会形成错误;
  • 否则,如果e是xvalue,decltype(e)则是T&&,其中T的类型是e ;
  • 否则,如果e是左值,decltype(e)则是T&,其中T的类型e;
  • 否则,decltype(e)是的类型e.

说明符的操作数decltype是未评估的操作数.

§5/ 6:

[ 注意:表达式是xvalue,如果它是:

  • 调用函数的结果,无论是隐式还是显式,其返回类型是对象类型的右值引用,
  • 强制转换为对象类型的右值引用,
  • 一个类成员访问表达式,指定非引用类型的非静态数据成员,其中对象表达式是xvalue,或者
  • 一个.*指针到构件表达,其中第一操作数是一个x值和第二个操作数是一个指向数据成员.

通常,此规则的作用是将命名的右值引用视为左值,将对象的未命名右值引用视为xvalues; 对函数的右值引用被视为左值,无论是否命名.- 结束说明 ]

我之前很谨慎,文字0可能会以某种方式阻止它在此上下文中作为对象类型进行限定,但§3.9/ 8澄清了一些事情:

一个对象类型是一个(可能CV修饰)键入不是一个函数式,而不是一个引用类型,而不是一个空隙型.

条件运算符不会影响这里的任何内容 - §5.16/ 4:

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

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