Ответ 1
Применяется сгибание, но не в С++ 11. В С++ 14 они будут применяться из-за http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270. Если вам повезет, Clang вернет это в свой режим С++ 11 (пусть надеется, что они будут!).
Предположим, что 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 является правильным для принятия.
Я признаю, что формулировка не особенно ясна. Итак, какой компилятор прав в своем лечении третьего фрагмента? Есть ли выравнивание фигурной скобки в инициализации списка или нет?
Применяется сгибание, но не в С++ 11. В С++ 14 они будут применяться из-за http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270. Если вам повезет, Clang вернет это в свой режим С++ 11 (пусть надеется, что они будут!).
Релевантно: 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