Почему '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 54

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 и стандарт, вероятно.