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

Предположим, нужно инициализировать 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 правильно принять.

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


person Community    schedule 07.06.2013    source источник
comment
Хороший вопрос! Возможно, стоит упомянуть, какой стандарт вы используете. Стандарт C ++ 11, а если нет, то какой именно проект.   -  person juanchopanza    schedule 07.06.2013
comment
инициализация, подобная присваиванию, называется инициализацией копирования. Он вызывает конструктор копирования, а не оператор присваивания.   -  person TemplateRex    schedule 07.06.2013
comment
@TemplateRex: вот почему я использовал работу вроде.   -  person    schedule 07.06.2013
comment
@juanchopanza: n3290, идентичный стандартному IIRC.   -  person    schedule 07.06.2013
comment
лучше использовать стандартную терминологию, люди запутаются и могут подумать, что вы не поняли, и ведут такие разговоры :-)   -  person TemplateRex    schedule 07.06.2013
comment
@TemplateRex: стандартная терминология в этом случае фактически является агрегированной инициализацией, если вы хотите быть педантичным. Все равно отредактировал.   -  person    schedule 07.06.2013
comment
Дублировать (см. этот вопрос)?   -  person maverik    schedule 07.06.2013
comment
@maverik: не совсем. Я спрашиваю о некоторых тонкостях инициализации списков, а не о совокупной инициализации.   -  person    schedule 07.06.2013
comment
не хочу быть педантичным, просто точным, потому что есть много вопросов по SO о путанице между присваиванием / копированием.   -  person TemplateRex    schedule 07.06.2013
comment
Ничего страшного, если использовать двойные скобки. Я не думаю, что это правда. Насколько мне известно, стандарт не дает никаких гарантий, что он работает с двойными скобами.   -  person Johannes Schaub - litb    schedule 08.06.2013
comment
К вашему сведению, в версии C ++ 11 Страуструпа «Язык программирования C ++» он использует прямую инициализацию списка в своем упрощенном примере Array (8.2.4, стр. 208) - но последнее слово, конечно же, относится к стандарту C ++ 11.   -  person maxschlepzig    schedule 09.03.2014


Ответы (2)


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

person Johannes Schaub - litb    schedule 07.06.2013
comment
На данный момент clang-5.0 в archlinux все еще не поддерживает удаление скобок даже с -std=c++17. - person Victor Polevoy; 01.10.2017