Here is some code:
int main()
{
using T = int[3];
T a;
a = T{};
}
As far as I can tell, this code is correct according to the C++17 Standard, however every compiler I tried rejected it.
Is this code actually incorrect? If so, by what clauses of the Standard?
My investigation so far: In C and in older versions of C++, the code was incorrect because the assignment operator's left operand must be a modifiable lvalue, which a
either wasn't, or it was unclearly specified. But since C++17 a
is clearly specified as a modifiable lvalue (C++17 [basic.lval]/7).
The array-to-pointer conversion is not applied here: [expr.ass] doesn't explicitly specify it, and [expr]/9 and [expr]/10 don't seem to apply: the =
expects a prvalue as right operand, and a prvalue was provided. (And it expects a glvalue as left operand, and a glvalue was provided). Those clauses apply if a glvalue was supplied where a prvalue was expected or vice versa.
[expr.ass]/3 says the right expression is implicitly converted to the type of the left operand . But since both sides have identical type int[3]
no conversion seems to be necessary.
So I see no clauses which would exclude [expr.ass]/2 from applying, that the value of the right-hand side is stored in the object referred to by the left.
The latest draft moves around the clauses that were in [basic.lval]/7 and [expr]/9-10 but doesn't seem to change their meaning, and it even re-words [expr.ass]/2 to be clearer:
In simple assignment (
=
), the object referred to by the left operand is modified by replacing its value with the result of the right operand.
a
is clearly specified as a modifiable lvalue (C++17 [basic.lval]/7)." -- May you quote that relevant text for a handy reference? – RevalueT{}
initializes all array elements to0
– Vittoriaa = b;
is ill-formed sinceb
is a glvalue, the array-to-pointer conversion is applied ([expr]/9) and then the pointer cannot be implicitly converted to the type ofa
; – Vittoria