这是当前草案中[Expr.Ref]/(4.2)和[Expr.sub]/1之间的矛盾

Is this a contradiction between [expr.ref]/(4.2) and [expr.sub]/1 in the current draft?

本文关键字:Expr sub 之间 矛盾 Ref 草案      更新时间:2023-10-16

根据[Expr.Ref]/(4.2(,并且A()是Prvalue,我们得出结论A().a[0]是xvalue。请参阅下面的突出显示句子。

如果E2是非静态数据成员,并且E1的类型为" CQ1 VQ1 X",则 E2的类型为" CQ2 VQ2 T",表达式指定了命名 第一个表达式指定对象的成员。如果E1是 lvalue,然后e1.e2是一个lvalue;否则e1.e2是xvalue。让 符号VQ12代表VQ1和VQ2的"联合";也就是说,如果VQ1或 VQ2是挥发性的,然后VQ12是挥发性的。同样,让符号 CQ12代表CQ1和CQ2的"联合";也就是说,如果CQ1或CQ2是 const,然后CQ12是const。如果宣布E2是可变成员, 然后e1.e2的类型为" VQ12 t"。如果不宣布E2是 可变成员,然后e1.e2的类型为" cq12 vq12 t。

因此,下面的摘要应编译。该代码不会在GCC中编译,也不在VS2017中编译,但它在Clang中编译。

#include<iostream>
struct A
{
    int a[3];
    A(): a{1, 2, 3} {}
};
int main()
{
    int &&r = A().a[0];
    std::cout << r << 'n';
}

但是,[expr.sub]/1中的措辞表明 a[0]是一个lvalue,无论 A()的值类别如何,这对我来说似乎是不正确的。

后缀表达式,然后在方括号中表达式是一个 后缀表达。其中一种表达式应为类型的glvalue " t的数组"或类型的"指针"和另一个类型 成为未引人注目的枚举或积分类型的贵族。结果就是 " T"类型。" t"类型应为完全定义的对象类型。 66 E1 [E2]表达式(按定义(与 *((E1( (E2(([ 注意:有关 *和 和11.3.4的详细信息,请参见8.5.2和8.5.6。 数组的详细信息。—End Note],,除了数组 操作数,结果是该操作数是一个lvalue,而结果是 xvalue否则。表达式E1在表达式之前进行测序 E2。

没有矛盾,您只是错误地解析了该表达式。如果我正确理解您,您是说E1A()E2a[0],是不是

实际上,E2a。因为.[]具有相同的优先级,因此该表达式解析为(A().a)[0]

这意味着根据[expr.ref] p4.2, A().a是xvalue(数组类型(,因此per per [expr.sub] p1 (A().a)[0]因此是xvalue。