f()。a [0]是一个xvalue吗? [英] Is `f().a[0]` an xvalue?

查看:111
本文介绍了f()。a [0]是一个xvalue吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  struct S {
int a [3] = {1,2,3};
};

S&& f(){return S();}

& f()。a; // [错误]取xvalue(右值引用)
& f()。a [0];的地址//在GCC 5.1.0和Clang 3.6.0中可以

S s;
& static_cast< S&>(s).a; // [错误]取xvalue(右值引用)
& static_cast< S&>(s).a [0];的地址。 //在GCC 5.1.0和Clang 3.6.0中可以确定




5.7表达式是xvalue的情况是:



(7.1)-调用函数的结果(隐式或显式),其返回类型是右值引用



(7.2)-转换为对对象类型的右值引用



(7.3)—类成员访问表达式,该对象指定非引用类型的非静态数据成员,其中对象表达式为xvalue,或者



(7.4)—一个指向成员的*表达式,其中第一个操作数是xvalue,第二个操作数是指向数据成员的指针。



5.2.1下标
后缀表达式后跟方括号中的表达式是后缀表达式。表达式
之一的类型应为 T 的数组或指向 T 的指针,并且另一个应具有无范围的枚举
或整数类型。结果的类型为 T 。类型 T 应为完全定义的对象类型。表达式 E1 [E2] (根据定义)与 *(((E1)+(E2))< ** t [注意:有关 *
+ 和8.3的详细信息,请参见5.3和5.7。 .4了解数组的详细信息。 —end note],,但对于数组操作数,如果该操作数是左值,则结果是左值,否则是xvalue。


那么, f()。a [0] 是一个xvalue吗?



我认为 f()。a [0] 应该是一个xvalue。






[Edit1]



忽略& f()。 a; & f()。a [0]; ,因为12.2 [class.temporary] p5.2


在函数return语句(6.6.3)中与返回值临时绑定的生存期未扩展
;临时变量将在return语句中的完整表达式结尾处被销毁。


static_cast< S&& ;>(s).a 是一个xvalue(7.2和7.3)。



,但对于数组操作数,如果该操作数为左值,则结果为左值,否则为xvalue。



所以我认为 static_cast< S&&> s.a [0] 应该是一个xvalue,但



& static_cast< S&> s.a [0]; //在GCC 5.1.0和Clang 3.6.0中可以



查询:



<我错了吗?如果我错了,请给我一个示例,给数组下标会得到一个xvalue。

解决方案

据我所知确实正确,这看起来是错误 ,尽管为了公平起见,最近使用 CWG缺陷1213 表示:


因为定义了下标操作作为通过指针值的间接寻址,应用于xvalue数组的下标运算符的结果是lvalue,而不是xvalue。


,而第5.2.1节[expr.sub]更改如下:


后缀表达式后跟方括号的表达式是
后缀表达式。其中一个表达式的类型应为
T的数组或指向T的指针,而另一个则应具有无范围的枚举或整数类型。结果是类型为
T的左值。类型 T应为完全定义的对象类型。62
表达式E1 [E2](根据定义)与*((E1)+(E2))相同[注:
参见*和+的详细信息分别为5.3 [expr.unary]和5.7 [expr.add],以及
的详细信息8.3.4 [dcl.array]的详细信息。 —end note] ,除了在数组操作数的情况下,如果该操作数
是一个左值,则结果是一个左值,否则是一个xvalue。


所以 f()。a [0]; static_cast< ; S&>(s).a [0] 应该是xvalues。



此缺陷直到2012年12月和 clang缺陷报告支持将该缺陷报告的支持列为未知,因此实现者很可能尚未修复此缺陷。



更新



提起叮当声错误报告:下标运算符应用于临时数组会导致左值


struct S{
    int a[3] = {1,2,3};
};

S&& f(){return S();}

&f().a;       //[Error] taking address of xvalue (rvalue reference)
&f().a[0];    //ok in GCC 5.1.0 and Clang 3.6.0

S s;
&static_cast<S&&>(s).a;     //[Error] taking address of xvalue (rvalue reference)
&static_cast<S&&>(s).a[0];  //ok in GCC 5.1.0 and Clang 3.6.0

5.7 An expression is an xvalue if it is:

(7.1) — the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type,

(7.2) — a cast to an rvalue reference to object type,

(7.3) — a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or

(7.4) — a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member.

5.2.1 Subscripting A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type "array of T" or "pointer to T" and the other shall have unscoped enumeration or integral type. The result is of type "T". The type "T" shall be a completely-defined object type. The expression E1[E2] is identical (by definition) to *((E1)+(E2))<<*t [ Note: see 5.3 and 5.7 for details of * and + and 8.3.4 for details of arrays. —end note ], except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.

So, is f().a[0] an xvalue?

I think f().a[0] should be an xvalue.


[Edit1]

Ignoring &f().a; and &f().a[0]; because 12.2[class.temporary]p5.2

The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement

static_cast<S&&>(s).a is an xvalue(7.2 and 7.3).

" except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise."

So I think static_cast<S&&>(s).a[0] should be an xvalue, but

&static_cast<S&&>(s).a[0]; //ok in GCC 5.1.0 and Clang 3.6.0

Questing:

Am I wrong? If I am wrong, show me an example that subscripting an array results an xvalue.

解决方案

As far as I can tell you are indeed correct, this looks a "bug", although to be fair this changed recently with CWG defect 1213 which says:

Because the subscripting operation is defined as indirection through a pointer value, the result of a subscript operator applied to an xvalue array is an lvalue, not an xvalue. This could be surprising to some.

and this changed section 5.2.1 [expr.sub] as follows:

A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type "array of T" or "pointer to T" and the other shall have unscoped enumeration or integral type. The result is an lvalue of type "T." The type "T" shall be a completely-defined object type.62 The expression E1[E2] is identical (by definition) to *((E1)+(E2)) [Note: see 5.3 [expr.unary] and 5.7 [expr.add] for details of * and + and 8.3.4 [dcl.array] for details of arrays. —end note], except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.

So indeed the result of f().a[0]; and static_cast<S&&>(s).a[0] should be xvalues.

This defect did not have a proposed resolution until December 2012 and clangs defect report support lists the support of that defect report as unknown so most likely the implementers have not gotten to fixing this defect yet.

Update

Filed a clang bug report: Subscript operator applied to an temporary array results in an lvalue.

这篇关于f()。a [0]是一个xvalue吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆