Предположим, что 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 является правильным для принятия.
Я признаю, что формулировка не особенно ясна. Итак, какой компилятор прав в своем лечении третьего фрагмента? Есть ли выравнивание фигурной скобки в инициализации списка или нет?