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.

+3


source to share


1 answer


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 it a[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.

+7


source







All Articles