Suppose there's an std::array
to be initialized. It's okay if using double braces:
std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
It's also okay to use single braces in the good old aggregate initialization, as the brace elision will take care of the missing braces:
std::array<int, 2> x = {0, 1};
However, is it okay to use list-initialization with single braces? GCC accepts it, Clang rejects it with "cannot omit braces around initialization of subobject when using direct list-initialization".
std::array<int, 2> x{0, 1};
The only part of the standard where brace elision is mentioned is 8.5.1/12, which says:
All implicit type conversions (Clause 4) are considered when initializing the aggregate member with an assignment-expression. If the assignment-expression can initialize a member, the member is initialized. Otherwise, if the member is itself a subaggregate, brace elision is assumed and the assignment-expression is considered for the initialization of the first member of the subaggregate.
8.5.1 is about aggregate initialization specifically, so that should mean Clang is correct to reject, right? Not so fast. 8.5.4/3 says:
List-initialization of an object or reference of type T is defined as follows:
[…]
— Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1).
I thinks it means that the exact same rules as with aggregate initialization, including brace elision, apply, meaning GCC is correct to accept.
I admit, the wording is not particularly clear. So, which compiler is right in its treatment of the third snippet? Does the brace elision happen in list-initialization, or it doesn't?
See Question&Answers more detail:os