This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of TS status.
optional<T> should 'forward' T's implicit conversionsSection: 5.3 [fund.ts.v2::optional.object] Status: TS Submitter: Geoffrey Romer Opened: 2014-10-31 Last modified: 2018-07-08
Priority: Not Prioritized
View all other issues in [fund.ts.v2::optional.object].
View all issues with TS status.
Discussion:
Addresses: fund.ts.v2
Code such as the following is currently ill-formed (thanks to STL for the compelling example):
optional<string> opt_str = "meow";
This is because it would require two user-defined conversions (from const char* to string,
and from string to optional<string>) where the language permits only one. This is
likely to be a surprise and an inconvenience for users.
optional<T> should be implicitly convertible from any U that is implicitly convertible
to T. This can be implemented as a non-explicit constructor template optional(U&&),
which is enabled via SFINAE only if is_convertible_v<U, T> and is_constructible_v<T, U>,
plus any additional conditions needed to avoid ambiguity with other constructors (see
N4064, particularly the
"Odd" example, for why is_convertible and is_constructible are both needed; thanks to Howard
Hinnant for spotting this).
In addition, we may want to support explicit construction from U, which would mean providing a corresponding
explicit constructor with a complementary SFINAE condition (this is the single-argument case of the "perfect
initialization" pattern described in N4064).
[2015-10, Kona Saturday afternoon]
STL: This has status LEWG, but it should be priority 1, since we cannot ship an IS without this.
TK: We assigned our own priorities to LWG-LEWG issues, but haven't actually processed any issues yet.
MC: This is important.
[2016-02-17, Ville comments and provides concrete wording]
I have prototype-implemented this wording in libstdc++. I didn't edit
the copy/move-assignment operator tables into the new
operator= templates that take optionals of a different
type; there's a drafting note that suggests copying them
from the existing tables.
[LEWG: 2016-03, Jacksonville]
Discussion of whether variant supports this. We think it does.
Proposed resolution:
This wording is relative to N4562.
Edit 22.5.3 [optional.optional] as indicated:
template <class T>
class optional
{
public:
typedef T value_type;
// 5.3.1, Constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
optional(const optional&);
optional(optional&&) noexcept(see below);
constexpr optional(const T&);
constexpr optional(T&&);
template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
[…]
// 5.3.3, Assignment
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional&);
optional& operator=(optional&&) noexcept(see below);
template <class U> optional& operator=(U&&);
template <class... Args> void emplace(Args&&...);
template <class U, class... Args>
void emplace(initializer_list<U>, Args&&...);
[…]
};
In 5.3.1 [fund.ts.v2::optional.object.ctor], insert new signature specifications after p33:
In 5.3.3 [fund.ts.v2::optional.object.assign], change as indicated:
template <class U> optional<T>& operator=(U&& v);-22- Remarks: If any exception is thrown, the result of the expression
bool(*this)remains unchanged. If an exception is thrown during the call toT's constructor, the state ofvis determined by the exception safety guarantee ofT's constructor. If an exception is thrown during the call toT's assignment, the state of*valandvis determined by the exception safety guarantee ofT's assignment. The function shall not participate in overload resolution unless.is_same_v<decay_t<U>, T>istrue-23- Notes: The reason for providing such generic assignment and then constraining it so that effectivelyT == Uis to guarantee that assignment of the formo = {}is unambiguous.