Is the field of a temporary object the value r?
This code compiles successfully under Clang 3.8, GCC 6.3 and VS2013, but does not work under Clang 4.0:
struct Foo {
int x[2];
Foo() {
x[0] = 3; // line A: works fine - we can assign to x[0]
*&x[0] = 4; // line B: works fine - we can take the address of x[0]
}
};
int main() {
Foo().x[0] = 5; // line C: error: expression is not assignable
*(Foo().x + 0) = 6; // line D: works fine
}
Which compiler is right? Is Foo().x[0]
r value or l value
Lines A and B work with all compilers, and is x[0]
definitely an lvalue, and lines A and B certainly refer to the same x
as line C, so it seems like there Foo().x[0]
should be an lvalue. But maybe the rvalue-ness of is Foo()
propagated to all of its fields when accessed this way?
Also consider line D, which works on all compilers. I thought I bar[n]
was basically just syntactic sugar for *(bar + n)
(for arrays), so it seems odd that line D works, but line C fails.
source to share
Foo().x[0]
was an lvalue in C ++ 11. In C ++ 11, the result of an inline index operator is always an lvalue, since it assumes a dereference of a pointer.
In C ++ 14, the behavior of the built-in index operator was changed:
- If
a
is an lvalue, then ita[i]
is an lvalue. - Otherwise, it
a[i]
is the value of x.
Foo()
is a prvalue, so accessing the non-stationary element gives the value x. Since Foo.x
is the value of x, Foo.x[0]
it is also the value of x and cannot be assigned.
source to share