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

Почему поведение С++ initializer_list для std::vector и std:: array отличается?

код:

std::vector<int> x{1,2,3,4};
std::array<int, 4> y{{1,2,3,4}};

Зачем мне нужны двойные фигурные скобки для std:: array?

4b9b3361

Ответ 1

std::array<T, N> - это совокупность: у него нет никаких объявленных пользователем конструкторов, даже один из них не принимает std::initializer_list. Инициализация с использованием фигурных скобок выполняется с использованием агрегатной инициализации, функции С++, которая была унаследована от C.

В "старом стиле" инициализации агрегата используется =:

std::array<int, 4> y = { { 1, 2, 3, 4 } };

В этом старом стиле инициализации агрегата могут быть отменены дополнительные фигурные скобки, поэтому это эквивалентно:

std::array<int, 4> y = { 1, 2, 3, 4 };

Однако эти дополнительные фигурные скобки могут быть отменены только "в объявлении формы T x = { a };" (С++ 11 §8.5.1/11), то есть когда используется старый стиль =. Это правило, разрешающее выравнивание фигур, не применяется для прямой инициализации списка. В сноске здесь говорится: "Скобки не могут быть удалены при других использованиях инициализации списка".

Существует отчет о дефекте относительно этого ограничения: дефект CWG # 1270. Если принятая предлагаемая резолюция будет принята, для других форм инициализации списка будет разрешено исключение фигурных скобок, и следующее будет хорошо сформировано:

std::array<int, 4> y{ 1, 2, 3, 4 };

(подсказка о шляпе Ville Voutilainen для поиска отчета о дефекте.)

Ответ 2

Потому что std::vector предлагает конструктор, который принимает std::initializer_list<T>, тогда как std::array не имеет конструкторов, а list {1, 2, 3, 4}, на самом деле не интерпретируется как std::initializer_list, но агрегатная инициализация для внутренний массив C-стиля std::array (тот, где второй набор фигурных скобок происходит от: One для std::array, один для внутреннего массива элементов C-стиля).