Предположим, нужно инициализировать 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 конкретно касается агрегированной инициализации, так что это должно означать, что Clang правильно отклоняет, не так ли? Не так быстро. 8.5.4 / 3 говорит:
Список-инициализация объекта или ссылки типа T определяется следующим образом:
[…]
- В противном случае, если T является агрегатом, выполняется инициализация агрегата (8.5.1).
Я думаю, это означает, что применяются те же правила, что и при агрегированной инициализации, включая исключение скобок, что означает, что GCC правильно принять.
Признаюсь, формулировка не особо ясна. Итак, какой компилятор прав в трактовке третьего фрагмента? Происходит ли исключение скобок при инициализации списка или нет?