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.
optional forwarding construction/assignmentSection: 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_lists are normally passed by
value) users of optional could naturally expect perfect forwarding of initializer_lists. 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
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.
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:
-28- Effects: Initializes the contained value as if constructing an object of typeis_constructible<T, initializer_list<U>&, Args&&...>::valueistrue.Twith the arguments,ilstd::forward<Args>(args).... […]-31- Remarks: The function shall not participate in overload resolution unlessis_constructible<T, initializer_list<U>&, Args&&...>::valueistrue.
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:
-28- Effects: Callsis_constructible<T, initializer_list<U>&, Args&&...>::valueistrue.*this = nullopt. Then initializes the contained value as if constructing an object of typeTwith the arguments,ilstd::forward<Args>(args).... […]-32- Remarks: This function shall not participate in overload resolution unlessis_constructible<T, initializer_list<U>&, Args&&...>::valueistrue.