Необязательный конструктор с параметром initializer_list

Какова цель этого специального конструктора, который принимает список инициализаторов. Может ли кто-нибудь привести пример того, когда это будет полезно?

template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);

Как это отличается от этого?

template <class... Args> constexpr explicit optional(in_place_t, Args&&... args); 

Ссылка: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html#optional.object.ctor

P.S. Не уверен, следует ли использовать тег С++ 14 или С++ 1z. Я думаю, что должен быть тег для технической спецификации С++

Ответ 1

Причиной для двух отдельных конструкторов является создание объектов, которые принимают initializer_list в качестве аргумента конструктора (необязательно, за которым следует произвольный список аргументов). Скажем, у вас есть тип foo, который выглядит так:

struct foo
{
    foo(std::initializer_list<int>) {}
};

В отсутствие конструктора

template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);

вы не сможете построить optional как

optional<foo> o(in_place, {1, 2, 3});

Вышеописанное не выполняется, потому что в файле с расширенным списком инициализации нет типа, поэтому вывод аргумента шаблона не выполняется. Вы должны прибегнуть к чему-то вроде этого:

auto il = {1, 2, 3};
optional<foo> o(in_place, il);

Наличие конструктора, который принимает аргумент initializer_list, позволяет создать более естественный синтаксис при создании объекта optional.

Здесь минимальный пример, демонстрирующий полезность двух конструкторов.