Почему не `std:: initializer_list` определяется как тип литерала?

Это продолжение этого вопроса: Является ли законным объявление объекта constexpr initializer_list?.

Так как С++ 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. Копирование списка инициализаторов не копирует основные элементы.
-end note]

Таким образом, для частных членов реализации initializer_list нет необходимости использовать типы нелетучих литералов; однако, поскольку они упоминают, что они считают, что пара указателей или указатель и длина будут "очевидным представлением", они, вероятно, не считают, что кто-то может помещать что-то нелитеральное в члены initializer_list.

Я бы сказал, что это как ошибка в clang, так и стандартная, возможно.