[optional.optional] (original) (raw)
22 General utilities library [utilities]
22.5 Optional objects [optional]
22.5.3 Class template optional [optional.optional]
22.5.3.1 General [optional.optional.general]
namespace std { template<class T> class optional { public: using value_type = T;using iterator = implementation-defined; using const_iterator = implementation-defined; constexpr optional() noexcept;constexpr optional(nullopt_t) noexcept;constexpr optional(const optional&);constexpr optional(optional&&) noexcept(see below);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&&...);template<class U = remove_cv_t<T>> constexpr explicit(see below) optional(U&&);template<class U> constexpr explicit(see below) optional(const optional<U>&);template<class U> constexpr explicit(see below) optional(optional<U>&&);constexpr ~optional();constexpr optional& operator=(nullopt_t) noexcept;constexpr optional& operator=(const optional&);constexpr optional& operator=(optional&&) noexcept(see below);template<class U = remove_cv_t<T>> constexpr optional& operator=(U&&);template<class U> constexpr optional& operator=(const optional<U>&);template<class U> constexpr optional& operator=(optional<U>&&);template<class... Args> constexpr T& emplace(Args&&...);template<class U, class... Args> constexpr T& emplace(initializer_list<U>, Args&&...);constexpr void swap(optional&) noexcept(see below);constexpr iterator begin() noexcept;constexpr const_iterator begin() const noexcept;constexpr iterator end() noexcept;constexpr const_iterator end() const noexcept;constexpr const T* operator->() const noexcept;constexpr T* operator->() noexcept;constexpr const T& operator*() const & noexcept;constexpr T& operator*() & noexcept;constexpr T&& operator*() && noexcept;constexpr const T&& operator*() const && noexcept;constexpr explicit operator bool() const noexcept;constexpr bool has_value() const noexcept;constexpr const T& value() const &; constexpr T& value() &; constexpr T&& value() &&; constexpr const T&& value() const &&; template<class U = remove_cv_t<T>> constexpr T value_or(U&&) const &;template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&;template<class F> constexpr auto and_then(F&& f) &;template<class F> constexpr auto and_then(F&& f) &&;template<class F> constexpr auto and_then(F&& f) const &;template<class F> constexpr auto and_then(F&& f) const &&;template<class F> constexpr auto transform(F&& f) &;template<class F> constexpr auto transform(F&& f) &&;template<class F> constexpr auto transform(F&& f) const &;template<class F> constexpr auto transform(F&& f) const &&;template<class F> constexpr optional or_else(F&& f) &&;template<class F> constexpr optional or_else(F&& f) const &;constexpr void reset() noexcept;private: T* val; };template<class T> optional(T) -> optional<T>;}
Any instance of optional<T> at any given time either contains a value or does not contain a value.
When an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional object's contained value, is nested within ([intro.object]) the optional object.
When an object of type optional<T> is contextually converted to bool, the conversion returns true if the object contains a value; otherwise the conversion returns false.
When an optional<T> object contains a value, member val points to the contained value.
T shall be a type other than cv in_place_t or cv nullopt_tthat meets the Cpp17Destructible requirements (Table 35).
22.5.3.2 Constructors [optional.ctor]
The exposition-only variable template _converts-from-any-cvref_is used by some constructors for optional.
template<class T, class W> constexpr bool converts-from-any-cvref = disjunction_v<is_constructible<T, W&>, is_convertible<W&, T>, is_constructible<T, W>, is_convertible<W, T>, is_constructible<T, const W&>, is_convertible<const W&, T>, is_constructible<T, const W>, is_convertible<const W, T>>;
constexpr optional() noexcept;constexpr optional(nullopt_t) noexcept;
Postconditions: *this does not contain a value.
Remarks: No contained value is initialized.
For every object type T these constructors are constexpr constructors ([dcl.constexpr]).
constexpr optional(const optional& rhs);
Effects: If rhs contains a value, direct-non-list-initializes the contained value with *rhs.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor is defined as deleted unlessis_copy_constructible_v<T> is true.
If is_trivially_copy_constructible_v<T> is true, this constructor is trivial.
constexpr optional(optional&& rhs) noexcept(_see below_);
Constraints: is_move_constructible_v<T> is true.
Effects: If rhs contains a value, direct-non-list-initializes the contained value with std::move(*rhs).
rhs.has_value() is unchanged.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: The exception specification is equivalent tois_nothrow_move_constructible_v<T>.
If is_trivially_move_constructible_v<T> is true, this constructor is trivial.
template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Constraints: is_constructible_v<T, Args...> is true.
Effects: Direct-non-list-initializes the contained value with std::forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.
template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes the contained value with il, std::forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.
template<class U = remove_cv_t<T>> constexpr explicit(_see below_) optional(U&& v);
Constraints:
- is_constructible_v<T, U> is true,
- is_same_v<remove_cvref_t<U>, in_place_t> is false,
- is_same_v<remove_cvref_t<U>, optional> is false, and
- if T is cv bool,remove_cvref_t<U> is not a specialization of optional.
Effects: Direct-non-list-initializes the contained value with std::forward<U>(v).
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
The expression inside explicit is equivalent to:!is_convertible_v<U, T>
template<class U> constexpr explicit(_see below_) optional(const optional<U>& rhs);
Constraints:
- is_constructible_v<T, const U&> is true, and
- if T is not cv bool,converts-from-any-cvref<T, optional<U>> is false.
Effects: If rhs contains a value, direct-non-list-initializes the contained value with *rhs.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside explicit is equivalent to:!is_convertible_v<const U&, T>
template<class U> constexpr explicit(_see below_) optional(optional<U>&& rhs);
Constraints:
- is_constructible_v<T, U> is true, and
- if T is not cv bool,converts-from-any-cvref<T, optional<U>> is false.
Effects: If rhs contains a value, direct-non-list-initializes the contained value with std::move(*rhs).
rhs.has_value() is unchanged.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside explicit is equivalent to:!is_convertible_v<U, T>
22.5.3.3 Destructor [optional.dtor]
Effects: If is_trivially_destructible_v<T> != true and *this contains a value, callsval->T::~T()
Remarks: If is_trivially_destructible_v<T> is true, then this destructor is trivial.
22.5.3.4 Assignment [optional.assign]
constexpr optional<T>& operator=(nullopt_t) noexcept;
Effects: If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no effect.
Postconditions: *this does not contain a value.
constexpr optional<T>& operator=(const optional& rhs);
Table 65 — optional::operator=(const optional&) effects [tab:optional.assign.copy]
🔗 | *this contains a value | *this does not contain a value |
---|---|---|
🔗rhs contains a value | assigns *rhs to the contained value | direct-non-list-initializes the contained value with *rhs |
🔗rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Postconditions: rhs.has_value() == this->has_value().
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's copy constructor, no effect.
If an exception is thrown during the call to T's copy assignment, the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
This operator is defined as deleted unlessis_copy_constructible_v<T> is true andis_copy_assignable_v<T> is true.
If is_trivially_copy_constructible_v<T> && is_trivially_copy_assignable_v<T> && is_trivially_destructible_v<T> is true, this assignment operator is trivial.
constexpr optional& operator=(optional&& rhs) noexcept(_see below_);
Constraints: is_move_constructible_v<T> is true andis_move_assignable_v<T> is true.
The result of the expression rhs.has_value() remains unchanged.
Table 66 — optional::operator=(optional&&) effects [tab:optional.assign.move]
🔗 | *this contains a value | *this does not contain a value |
---|---|---|
🔗rhs contains a value | assigns std::move(*rhs) to the contained value | direct-non-list-initializes the contained value with std::move(*rhs) |
🔗rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Postconditions: rhs.has_value() == this->has_value().
Remarks: The exception specification is equivalent to:is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>
If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's move constructor, the state of *rhs.val is determined by the exception safety guarantee of T's move constructor.
If an exception is thrown during the call to T's move assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's move assignment.
If is_trivially_move_constructible_v<T> && is_trivially_move_assignable_v<T> && is_trivially_destructible_v<T> is true, this assignment operator is trivial.
template<class U = remove_cv_t<T>> constexpr optional& operator=(U&& v);
Constraints:
- is_same_v<remove_cvref_t<U>, optional> is false,
- conjunction_v<is_scalar<T>, is_same<T, decay_t<U>>> is false,
- is_constructible_v<T, U> is true, and
- is_assignable_v<T&, U> is true.
Effects: If *this contains a value, assigns std::forward<U>(v) to the contained value; otherwise direct-non-list-initializes the contained value with std::forward<U>(v).
Postconditions: *this contains a value.
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's constructor, the state of v is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and v is determined by the exception safety guarantee of T's assignment.
template<class U> constexpr optional<T>& operator=(const optional<U>& rhs);
Constraints:
- is_constructible_v<T, const U&> is true,
- is_assignable_v<T&, const U&> is true,
- converts-from-any-cvref<T, optional<U>> is false,
- is_assignable_v<T&, optional<U>&> is false,
- is_assignable_v<T&, optional<U>&&> is false,
- is_assignable_v<T&, const optional<U>&> is false, and
- is_assignable_v<T&, const optional<U>&&> is false.
Table 67 — optional::operator=(const optional<U>&) effects [tab:optional.assign.copy.templ]
🔗 | *this contains a value | *this does not contain a value |
---|---|---|
🔗rhs contains a value | assigns *rhs to the contained value | direct-non-list-initializes the contained value with *rhs |
🔗rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Postconditions: rhs.has_value() == this->has_value().
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's constructor, the state of *rhs.val is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's assignment.
template<class U> constexpr optional<T>& operator=(optional<U>&& rhs);
Constraints:
- is_constructible_v<T, U> is true,
- is_assignable_v<T&, U> is true,
- converts-from-any-cvref<T, optional<U>> is false,
- is_assignable_v<T&, optional<U>&> is false,
- is_assignable_v<T&, optional<U>&&> is false,
- is_assignable_v<T&, const optional<U>&> is false, and
- is_assignable_v<T&, const optional<U>&&> is false.
The result of the expression rhs.has_value() remains unchanged.
Table 68 — optional::operator=(optional<U>&&) effects [tab:optional.assign.move.templ]
🔗 | *this contains a value | *this does not contain a value |
---|---|---|
🔗rhs contains a value | assigns std::move(*rhs) to the contained value | direct-non-list-initializes the contained value with std::move(*rhs) |
🔗rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Postconditions: rhs.has_value() == this->has_value().
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's constructor, the state of *rhs.val is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's assignment.
template<class... Args> constexpr T& emplace(Args&&... args);
Mandates: is_constructible_v<T, Args...> is true.
Effects: Calls *this = nullopt.
Then direct-non-list-initializes the contained value with std::forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.
template<class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Calls *this = nullopt.
Then direct-non-list-initializes the contained value withil, std::forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.
22.5.3.5 Swap [optional.swap]
constexpr void swap(optional& rhs) noexcept(_see below_);
Mandates: is_move_constructible_v<T> is true.
Table 69 — optional::swap(optional&) effects [tab:optional.swap]
🔗 | *this contains a value | *this does not contain a value |
---|---|---|
🔗rhs contains a value | calls swap(*(*this), *rhs) | direct-non-list-initializes the contained value of *thiswith std::move(*rhs), followed by rhs.val->T::~T(); postcondition is that *this contains a value and rhs does not contain a value |
🔗rhs does not contain a value | direct-non-list-initializes the contained value of rhswith std::move(*(*this)), followed by val->T::~T(); postcondition is that *this does not contain a value and rhs contains a value | no effect |
Throws: Any exceptions thrown by the operations in the relevant part of Table 69.
Remarks: The exception specification is equivalent to:is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
If any exception is thrown, the results of the expressions this->has_value() and rhs.has_value() remain unchanged.
If an exception is thrown during the call to function swap, the state of *val and *rhs.val is determined by the exception safety guarantee of swap for lvalues of T.
If an exception is thrown during the call to T's move constructor, the state of *val and *rhs.val is determined by the exception safety guarantee of T's move constructor.
22.5.3.6 Iterator support [optional.iterators]
using iterator = _implementation-defined_;using const_iterator = _implementation-defined_;
The reference type is T& for iterator andconst T& for const_iterator.
All requirements on container iterators ([container.reqmts]) apply tooptional::iterator and optional::const_iterator as well.
Any operation that initializes or destroys the contained value of an optional object invalidates all iterators into that object.
constexpr iterator begin() noexcept;constexpr const_iterator begin() const noexcept;
Returns: If has_value() is true, an iterator referring to the contained value.
Otherwise, a past-the-end iterator value.
constexpr iterator end() noexcept;constexpr const_iterator end() const noexcept;
Returns: begin() + has_value().
22.5.3.7 Observers [optional.observe]
constexpr const T* operator->() const noexcept;constexpr T* operator->() noexcept;
Hardened preconditions: has_value() is true.
Remarks: These functions are constexpr functions.
constexpr const T& operator*() const & noexcept;constexpr T& operator*() & noexcept;
Hardened preconditions: has_value() is true.
Remarks: These functions are constexpr functions.
constexpr T&& operator*() && noexcept;constexpr const T&& operator*() const && noexcept;
Hardened preconditions: has_value() is true.
Effects: Equivalent to: return std::move(*val);
constexpr explicit operator bool() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function is a constexpr function.
constexpr bool has_value() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function is a constexpr function.
constexpr const T& value() const &;constexpr T& value() &;
Effects: Equivalent to:return has_value() ? *val : throw bad_optional_access();
constexpr T&& value() &&;constexpr const T&& value() const &&;
Effects: Equivalent to:return has_value() ? std::move(*val) : throw bad_optional_access();
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
Mandates: is_copy_constructible_v<T> && is_convertible_v<U&&, T> is true.
Effects: Equivalent to:return has_value() ? **this : static_cast<T>(std::forward<U>(v));
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
Mandates: is_move_constructible_v<T> && is_convertible_v<U&&, T> is true.
Effects: Equivalent to:return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
22.5.3.8 Monadic operations [optional.monadic]
template<class F> constexpr auto and_then(F&& f) &;template<class F> constexpr auto and_then(F&& f) const &;
Let U be invoke_result_t<F, decltype(*val)>.
Mandates: remove_cvref_t<U> is a specialization of optional.
Effects: Equivalent to:if (*this) { return invoke(std::forward<F>(f), *val);} else { return remove_cvref_t<U>();}
template<class F> constexpr auto and_then(F&& f) &&;template<class F> constexpr auto and_then(F&& f) const &&;
Let U be invoke_result_t<F, decltype(std::move(*val))>.
Mandates: remove_cvref_t<U> is a specialization of optional.
Effects: Equivalent to:if (*this) { return invoke(std::forward<F>(f), std::move(*val));} else { return remove_cvref_t<U>();}
template<class F> constexpr auto transform(F&& f) &;template<class F> constexpr auto transform(F&& f) const &;
Let U be remove_cv_t<invoke_result_t<F, decltype(*val)>>.
Mandates: U is a non-array object type other than in_place_t or nullopt_t.
The declarationU u(invoke(std::forward<F>(f), *val));is well-formed for some invented variable u.
Returns: If *this contains a value, an optional<U> object whose contained value is direct-non-list-initialized withinvoke(std::forward<F>(f), *val); otherwise, optional<U>().
template<class F> constexpr auto transform(F&& f) &&;template<class F> constexpr auto transform(F&& f) const &&;
Let U beremove_cv_t<invoke_result_t<F, decltype(std::move(*val))>>.
Mandates: U is a non-array object type other than in_place_t or nullopt_t.
The declarationU u(invoke(std::forward<F>(f), std::move(*val)));is well-formed for some invented variable u.
Returns: If *this contains a value, an optional<U> object whose contained value is direct-non-list-initialized withinvoke(std::forward<F>(f), std::move(*val)); otherwise, optional<U>().
template<class F> constexpr optional or_else(F&& f) const &;
Mandates: is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is true.
Effects: Equivalent to:if (*this) { return *this;} else { return std::forward<F>(f)();}
template<class F> constexpr optional or_else(F&& f) &&;
Mandates: is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is true.
Effects: Equivalent to:if (*this) { return std::move(*this);} else { return std::forward<F>(f)();}
22.5.3.9 Modifiers [optional.mod]
constexpr void reset() noexcept;
Effects: If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no effect.
Postconditions: *this does not contain a value.