条件表达式中的右值引用

时间:2012-04-28 00:51:23

标签: c++ gcc c++11 clang decltype

typedef decltype(true ? (long&&)0 : (long&&)0) T;

应该是什么?

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

更新:正如 ildjarn 指出的那样,Clang是对的,正如 Richard Smith 指出的那样,错误libstdc ++是由于错误在标准中。这是relevant GCC bugrelevant Defect Report

1 个答案:

答案 0 :(得分:5)

Clang是对的。 N3337§7.1.6.2/ 4:

  

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

     
      
  • 如果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,或
  •   
  • .*指向成员的表达式,其中第一个操作数是xvalue,第二个操作数是指向数据成员的指针。
  •   
     

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

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

  

对象类型是一种(可能是cv限定的)类型,它不是函数类型,不是引用类型,也不是void类型。

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

  

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

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