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

T 应该是什么?

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

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

4

1 回答 1

5

叮当是对的。N3337 §7.1.6.2/4:

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

  • ife是无括号的id 表达式或无括号的类成员访问,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,第二个操作数是一个指向数据成员的指针。

一般来说,这条规则的效果是命名的右值引用被视为左值,而对对象的未命名的右值引用被视为xvalue;对函数的右值引用被视为左值,无论是否命名。——<em>尾注]

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

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

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

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

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

于 2012-04-28T01:29:37.460 回答