Почему 'std::initializer list' не определен как литеральный тип?
Это продолжение этого вопроса: законно ли объявлять объект constexpr initializer_list?.
начиная с C++14,std::initializer_list
класс имеет все свои методы, помеченные constexpr
. Кажется естественным иметь возможность инициализировать экземпляр, выполнив
constexpr std::initializer_list<int> list = {1, 2, 3};
но Clang 3.5 жалуется на list
не инициализируется константным выражением.
как dyp указал в комментарии, каких-либо требований к std::initializer_list
буквальным типа исчез из спецификации.
какой смысл иметь класс, полностью определенный как constexpr, если мы даже не можем инициализировать его как таковой? Является ли это упущением в стандарте и будет исправлено в будущем?
1 ответ:
комитет по стандартизации, похоже, намерен
initializer_list
будучи литеральным типом. Однако это не похоже на явное требование и, похоже, является ошибкой в стандарте.из § 3.9.10.5:
тип литерал типа если это:
- тип класса (пункт 9), который имеет все следующие свойства:
- - он имеет тривиальный деструктор,
- - это агрегатный тип (8.5.1) или имеет по крайней мере один constexpr конструктор или шаблон конструктора, который не является конструктором копирования или перемещения, и
- - все его нестатические члены данных и базовые классы имеют энергонезависимые литеральные типы.из § 18.9.1:
namespace std { template<class E> class initializer_list { public: /* code removed */ constexpr initializer_list() noexcept; // No destructor given, so trivial /* code removed */ }; }
это удовлетворяет первое и второе требования.
для третьего требования, хотя:
из § 18.9.2 (выделено мной):
объект типа
initializer_list<E>
обеспечивает доступ к массиву объектов типаconst E
. [Примечание:пара указателей или указатель плюс длина было бы очевидно представления дляinitializer_list
.initializer_list
используется для реализации списков инициализаторов, как указано в 8.5.4. Копирование списка инициализаторов не копирует базовые элементы.
-конец Примечание]таким образом, нет никаких требований к частным членам реализации
initializer_list
быть энергонезависимыми литеральными типами; однако, поскольку они упомяните, что они считают, что пара указателей или указатель и длина будут "очевидным представлением", они, вероятно, не считали, что кто-то может поместить что-то нелитеральное в членыinitializer_list
.Я бы сказал, что это и ошибка в clang и стандарт, вероятно.