Brace elision in std::array initialization
Asked Answered
H

2

48

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?

Hoopoe answered 7/6, 2013 at 13:45 Comment(11)
Nice question! It might be worth mentioning which standard you are using. The C++11 standard, or if not, which particular draft.Urias
"assignment-like initialization" is called copy-initialization. It calls the copy constructor, not the assignment operator.Unilobed
@TemplateRex: that's why I used the work "like".Hoopoe
@juanchopanza: n3290, which is identical to the standard IIRC.Hoopoe
it's better to use the standard terminology, people get confused and might think you didn't understand and have conversations like this one :-)Unilobed
@TemplateRex: the standard terminology in this case is actually aggregate initialization, if you want to be pedantic. Edited, anyway.Hoopoe
Duplicate (see this question)?Woodford
@maverik: not really. I'm asking about some specific intricacies of list-initialization, not about aggregate initialization.Hoopoe
not meaning to be pedantic, just precise, because there are many questions on SO about confusion between assignment/copying.Unilobed
"It's okay if using double braces". I don't think that's true. The standard gives no guarantee that it works with double braces, as far as I know.Stillborn
Fyi, in the C++11 edition of Stroustrup's 'The C++ programming language' he uses direct list initialization in his simplified Array example (8.2.4, page 208) - but the last word has the C++ 11 standard, of course.Coahuila
S
25

Brace elision applies, but not in C++11. In C++14, they will apply because of http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270 . If you are lucky, Clang will backport that to their C++11 mode (let's hope they will!).

Stillborn answered 7/6, 2013 at 21:12 Comment(1)
As of now, clang-5.0 in the archlinux still does not support brace elision even with -std=c++17.Hellenist
B
12

Relevant: http://en.cppreference.com/w/cpp/language/aggregate_initialization

In short,

struct S {
    int x;
    struct Foo {
        int i;
        int j;
        int a[3];
    } b;
};
S s1 = { 1, { 2, 3, {4, 5, 6} } };
S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision
S s3{1, {2, 3, {4, 5, 6} } }; // same, using direct-list-initialization syntax
S s4{1, 2, 3, 4, 5, 6}; // error in C++11: brace-elision only allowed with equals sign
                        // okay in C++14
Bergamo answered 5/3, 2015 at 23:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.