This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.

### 2305. [fund.ts] `optional` forwarding construction/assignment

Section: 5.3.1 [fund.ts::optional.object.ctor] Status: NAD Submitter: Cassio Neri Opened: 2013-09-23 Last modified: 2015-10-26

Priority: 4

View all issues with NAD status.

Discussion:

Addresses: fund.ts

Consider:

>     struct foo {
>       foo(std::initializer_list<int>&);        // 1
>       foo(const std::initializer_list<int>&);  // 2
>       foo(std::initializer_list<int>&&);       // 3
>       foo(const std::initializer_list<int>&&); // 4
>     };

>     std::initializer_list<int> il{0, 1, 2};

>     foo foo_0{1, 2, 3};                                 // calls 3
>     foo foo_1{il};                                      // calls 1
>     foo foo_2((const std::initializer_list<int>&) il);  // calls 2
>     foo foo_3{(std::initializer_list<int>&&) il};       // calls 3
>     foo foo_4((const std::initializer_list<int>&&) il); // calls 4

Although the constructors of `foo` are unusual (`initializer_list`s are normally passed by value) users of `optional` could naturally expect perfect forwarding of `initializer_list`s. However, all lines below end up calling 1.

>     optional<foo> opt0{in_place, {1, 2, 3}};
>     optional<foo> opt1{in_place, il};
>     optional<foo> opt3{in_place, (const std::initializer_list<int>&) il};
>     optional<foo> opt2{in_place, (std::initializer_list<int>&&) il};
>     optional<foo> opt4{in_place, (const std::initializer_list<int>&&) il};

>     opt0.emplace({1, 2, 3});
>     opt0.emplace(il);
>     opt0.emplace((const std::initializer_list<int>&) il);
>     opt0.emplace((std::initializer_list<int>&&) il);
>     opt0.emplace((const std::initializer_list<int>&&) il);

The constructor

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

can handle all constructor calls above, except the one taking `{1, 2, 3}`. Hence, a simple modification of

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

allows perfect forwarding of `std::initializer_list<U>`s to be complete.

[2014-06-06 pre-Rapperswil]

This issue has been reopened as fundamentals-ts.

[2014-06-17, Rapperswil]

Move to NAD

Proposed resolution:

This wording is relative to N3691.

1. Change 5.3.1 [fund.ts::optional.object.ctor] as indicated:

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

   > > -27- Requires: `is_constructible<T, initializer_list<U>&&, Args&&...>::value` is `true.`

   > > -28- Effects: Initializes the contained value as if constructing an object of type `T` with the arguments `ilstd::move(il)`, `std::forward<Args>(args)...`.

   > > […]

   > > -31- Remarks: The function shall not participate in overload resolution unless `is_constructible<T, initializer_list<U>&, Args&&...>::value` is `true`.

2. Change 5.3.3 [fund.ts::optional.object.assign] as indicated:

   >     template <class U, class... Args>
   >     void optional<T>::emplace(initializer_list<U>&& il, Args&&... args);

   > > -27- Requires: `is_constructible<T, initializer_list<U>&&, Args&&...>::value` is `true.`

   > > -28- Effects: Calls `*this = nullopt`. Then initializes the contained value as if constructing an object of type `T` with the arguments `ilstd::move(il)`, `std::forward<Args>(args)...`.

   > > […]

   > > -32- Remarks: This function shall not participate in overload resolution unless `is_constructible<T, initializer_list<U>&, Args&&...>::value` is `true.`