std::initializer_list
создается компилятором из списка инициализации, заключенного в скобки, и размер этого списка должен быть постоянной времени компиляции.
Итак, почему комитет решил опустить размер из аргументов шаблона? Это, возможно, предотвращает некоторые оптимизации и делает некоторые вещи невозможными (инициализация std::array
от std::initializer_list
).
Ответ 1
Один из достоинств существующей системы заключается в том, что вы можете экспортировать функции, которые принимают initializer_list
из DLL. Если бы они были заархивированы по размеру, они должны были быть отправлены в качестве источника.
Ответ 2
Если initializer_list
было определено как std::initializer_list<type, size>
, то любая функция, которая принимает initializer_list<type>
, где type
- это конкретный тип, теперь должна быть функцией шаблона, основанной на этом размере списка. Или они должны будут потребовать, чтобы пользователи передали initializer_list
определенного типа и размера.
Оба они довольно неприемлемы. Не все записывают весь свой код в качестве шаблонов.
Вы можете инициализировать std::array
из скопированного-init-списка ({}
с материалом в середине). Но это не то же самое, что std::intiializer_list
. Класс array
является агрегированным типом. Это структура, которая содержит один элемент, который является открытым массивом. Следовательно, на соответствующих реализациях С++ 11 это должно скомпилировать:
std::array<int, 3> myArray = {1, 3, 5};
Однако {1, 3, 5}
не является объектом std::initializer_list
; это просто бит-init-list, который можно использовать для инициализации соответствующих типов.
Вы не можете передать объект std::initializer_list
конструктору aggegate (поскольку агрегаты не имеют конструкторов), но вы можете использовать список braced-init для вызова инициализации агрегата для инициализации std::array
, как и вы для любой структуры, содержащей массив.
Разница между std::initializer_list
и braced-init-list немного похожа на разницу между int
и литералом 0
. Это не (обычно) законно неявно преобразовывать объект int
в тип указателя, но законно неявно преобразовывать целочисленный литерал 0 в тип указателя. Способ работы с бит-init-списками выглядит следующим образом:
int i = 0; //Legal
void *j = 0; //Legal
void *k = i; //Not legal
std::array<int, 3> myArray = {1, 3, 5}; //Legal
std::initializer_list<int> myInitList = {1, 3, 5}; //Legal
std::array<int, 3> myArray = myInitList; //Not legal