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 bug和relevant Defect Report。
答案 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。