Brace elision in std::array initialization

[亡魂溺海] 提交于 2019-11-26 16:23:36

问题


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?


回答1:


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!).




回答2:


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


来源:https://stackoverflow.com/questions/16985687/brace-elision-in-stdarray-initialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!