Подтвердить что ты не робот

Выравнивание брекета в инициализации std:: array

Предположим, что a std::array будет инициализирован. Это нормально, если использовать двойные фигурные скобки:

std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};

Также хорошо использовать одиночные фигурные скобки в старой старой инициализации агрегата, так как выравнивание фигур будет касаться отсутствующих фигурных скобок:

std::array<int, 2> x = {0, 1};

Однако, хорошо ли использовать инициализацию списка с помощью отдельных фигурных скобок? GCC принимает его, Clang отклоняет его с помощью "не может опустить скобки вокруг инициализации подобъекта при использовании прямой инициализации списка".

std::array<int, 2> x{0, 1};

Единственная часть стандарта, в которой упоминается ссылка: 8.5.1/12, в которой говорится:

Все неявные преобразования типов (раздел 4) рассматриваются при инициализации элемента агрегата с помощью выражения-присваивания. Если выражение-присваивание может инициализировать элемент, элемент инициализируется. В противном случае, если элемент сам является субагрегатом, предполагается выравнивание фигурной скобки и рассматривается выражение-присваивание для инициализации первого элемента субагрегата.

8.5.1 относится к агрегатной инициализации конкретно, так что это должно означать, что Клэнт правильно отклоняет, правильно? Не так быстро. 8.5.4/3 гласит:

Список-инициализация объекта или ссылки типа T определяется следующим образом:

[...]

- В противном случае, если T является агрегатом, выполняется агрегатная инициализация (8.5.1).

Я думаю, это означает, что применяются те же самые правила, что и при инициализации агрегата, включая выравнивание фигурной скобки, что означает, что GCC является правильным для принятия.

Я признаю, что формулировка не особенно ясна. Итак, какой компилятор прав в своем лечении третьего фрагмента? Есть ли выравнивание фигурной скобки в инициализации списка или нет?

4b9b3361

Ответ 1

Применяется сгибание, но не в С++ 11. В С++ 14 они будут применяться из-за http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270. Если вам повезет, Clang вернет это в свой режим С++ 11 (пусть надеется, что они будут!).

Ответ 2

Релевантно: http://en.cppreference.com/w/cpp/language/aggregate_initialization

Короче говоря,

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