Является ли законным объявление объекта constexpr initializer_list?

В качестве вопроса, который возник при обсуждении этого SO-вопроса:

Является ли это законным, возможно, с N3471, чтобы объявить объект constexpr std::initializer_list? Пример:

constexpr std::initializer_list<int> my_list{};

Почему я думаю, что это может быть не законным: initializer_list должен быть буквальным типом; но есть ли какие-либо гарантии, что это буквальный тип?

Цитаты из N3485.

[dcl.constexpr]/9:

Спецификатор constexpr, используемый в объявлении объекта, объявляет объект как const. Такой объект должен иметь буквальный тип и должен быть инициализирован.

литеральные типы типов, [basic.types]/10, типы подпункта:

  • тип класса (раздел 9), который имеет все следующие свойства:
    • он имеет тривиальный деструктор,
    • каждый вызов конструктора и полноэкранное выражение в элементарных элементах для нестатических данных (если они есть) является константным выражением (5.19),
    • это тип агрегата (8.5.1) или имеет хотя бы один конструктор конструктора или конструктора constexpr, который не является конструктором копирования или перемещения, и
    • все его нестатические элементы данных и базовые классы являются нелетучими литералами.

Бонусные точки;) для ответа, если

constexpr std::initializer_list<int> my_list = {1,2,3,4,5};

является законным (со ссылками). Хотя я думаю, что это описано выше + [dcl.init.list]/5

Ответы

Ответ 1

Обновление: Ситуация немного усложнилась после того, как разрешение CWG DR 1684 удалило указанное требование ниже. Более подробную информацию можно найти в эту дискуссию в списке рассылки std-обсуждения и в соответствующем вопросе Почему не `std:: initializer_list` определяется как тип литерала?


[decl.constexpr]/8:

Спецификатор constexpr для нестатической функции-члена, которая не является конструктором, объявляет, что функция-член является константой (9.3.1). [...] Класс, членом которого является член, должен быть буквальный тип (3.9).

Следовательно, изменения гарантии N3471 std::initializer_list будут буквальными.


Обратите внимание, что constexpr ctor не требует, чтобы std::initializer_list был литеральным типом, см. [dcl.constexpr]/4 + 8. Замечание: объект нелитерального типа с constexpr ctor может быть инициализирован при постоянной инициализации [basic.start.init]/2] (часть статической инициализации, выполняемая до любой динамической инициализации).