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.
However to answer you question you can NOT assign one array to another. The compiler will not allow this. Show activity on this post.
In C++ the equality test == may be applied to arrays, but the assignment operator = cannot be applied to arrays.
You can't assign arrays in C++, it's stupid but it's true. You have to copy the array elements one by one. Or you could use a built in function like memcpy or std::copy . Or you could give up on arrays, and use std::vector instead.
As far as I can tell, the definition of "modifiable lvalue" is either under-specified in C++, or arrays have been intentionally been specified to be assignable (I suspect that former is true, since no compiler does latter).
The standard (latest draft) says:
[basic.lval]
An lvalue is modifiable unless its type is const-qualified or is a function type.
This is quite concise, but there is no exclusion of arrays.
Furthermore, this hasn't changed through standard versions at least since C++03, which specifies following:
[basic.lval]
11 Functions cannot be modified, but pointers to functions can be modifiable.
12 A pointer to an incomplete type can be modifiable. ...
13 The referent of a const-qualified expression shall not be modified ...
Which is mostly same, except using more descriptive than definitive wording. No exclusion of arrays.
By contrast, C11 standard is crystal clear (quoting N1548 draft):
6.3.2.1 Lvalues, arrays, and function designators
1 ... A modifiable lvalue is an lvalue that does not have array type, ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With