Created on 2013-09-23.00:00:00 last changed 126 months ago
Proposed resolution:
This wording is relative to N3691.
Change [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 argumentsilstd::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.
Change [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 argumentsilstd::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.
[ 2014-06-17, Rapperswil ]
Move to NAD
[ 2014-06-06 pre-Rapperswil ]
This issue has been reopened as fundamentals-ts.
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 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.
History | |||
---|---|---|---|
Date | User | Action | Args |
2014-06-17 21:17:35 | admin | set | messages: + msg7064 |
2014-06-17 21:17:35 | admin | set | status: open -> nad |
2014-06-06 21:18:30 | admin | set | messages: + msg6997 |
2014-06-06 21:18:30 | admin | set | status: deferred -> open |
2013-10-07 20:36:11 | admin | set | messages: + msg6680 |
2013-09-23 00:00:00 | admin | create |