template <class T> class optional { public: using value_type = T; // [optional.ctor], constructors 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 = T> EXPLICIT constexpr optional(U&&); template <class U> EXPLICIT optional(const optional<U>&); template <class U> EXPLICIT optional(optional<U>&&); // [optional.dtor], destructor ~optional(); // [optional.assign], assignment optional& operator=(nullopt_t) noexcept; optional& operator=(const optional&); optional& operator=(optional&&) noexcept(see below); template <class U = T> optional& operator=(U&&); template <class U> optional& operator=(const optional<U>&); template <class U> optional& operator=(optional<U>&&); template <class... Args> T& emplace(Args&&...); template <class U, class... Args> T& emplace(initializer_list<U>, Args&&...); // [optional.swap], swap void swap(optional&) noexcept(see below); // [optional.observe], observers constexpr const T* operator->() const; constexpr T* operator->(); constexpr const T& operator*() const&; constexpr T& operator*() &; constexpr T&& operator*() &&; constexpr const T&& operator*() const&&; 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> constexpr T value_or(U&&) const&; template <class U> constexpr T value_or(U&&) &&; // [optional.mod], modifiers void reset() noexcept; private: T *val; // exposition only }; 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 allocated within the storage of the optional object. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value. The contained value shall be allocated in a region of the optional<T> storage suitably aligned for the type T. 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.
Member val is provided for exposition only. When an optional<T> object contains a value, val points to the contained value.
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
Remarks: No contained value is initialized. For every object type T these constructors shall be constexpr constructors.
constexpr optional(const optional& rhs);
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression *rhs.
Remarks: This constructor shall be defined as deleted unless is_copy_constructible_v<T> is true. If is_trivially_copy_constructible_v<T> is true, this constructor shall be a constexpr constructor.
constexpr optional(optional&& rhs) noexcept(see below);
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression std::move(*rhs). bool(rhs) is unchanged.
Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible_v<T>. This constructor shall not participate in overload resolution unless is_move_constructible_v<T> is true. If is_trivially_move_constructible_v<T> is true, this constructor shall be a constexpr constructor.
template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor. This constructor shall not participate in overload resolution unless is_constructible_v<T, Args...> is true.
template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....
Remarks: This constructor shall not participate in overload resolution unless is_constructible_v<T, initializer_list<U>&, Args&&...> is true. If T's constructor selected for the initialization is a constexpr constructor, this constructor shall be a constexpr constructor.
[ Note: The following constructors are conditionally specified as explicit. This is typically implemented by declaring two such constructors, of which at most one participates in overload resolution. — end note ]
template <class U = T> EXPLICIT constexpr optional(U&& v);
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the expression std::forward<U>(v).
Remarks: If T's selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor. This constructor shall not participate in overload resolution unless is_constructible_v<T, U&&> is true, is_same_v<decay_t<U>, in_place_t> is false, and is_same_v<optional<T>, decay_t<U>> is false. The constructor is explicit if and only if is_convertible_v<U&&, T> is false.
template <class U> EXPLICIT optional(const optional<U>& rhs);
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression *rhs.
Remarks: This constructor shall not participate in overload resolution unless
is_constructible_v<T, const U&> is true,
is_constructible_v<T, optional<U>&> is false,
is_constructible_v<T, optional<U>&&> is false,
is_constructible_v<T, const optional<U>&> is false,
is_constructible_v<T, const optional<U>&&> is false,
is_convertible_v<optional<U>&, T> is false,
is_convertible_v<optional<U>&&, T> is false,
is_convertible_v<const optional<U>&, T> is false, and
is_convertible_v<const optional<U>&&, T> is false.
The constructor is explicit if and only if is_convertible_v<const U&, T> is false.
template <class U> EXPLICIT optional(optional<U>&& rhs);
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object of type T with the expression std::move(*rhs). bool(rhs) is unchanged.
Remarks: This constructor shall not participate in overload resolution unless
is_constructible_v<T, U&&> is true,
is_constructible_v<T, optional<U>&> is false,
is_constructible_v<T, optional<U>&&> is false,
is_constructible_v<T, const optional<U>&> is false,
is_constructible_v<T, const optional<U>&&> is false,
is_convertible_v<optional<U>&, T> is false,
is_convertible_v<optional<U>&&, T> is false,
is_convertible_v<const optional<U>&, T> is false, and
is_convertible_v<const optional<U>&&, T> is false.
The constructor is explicit if and only if is_convertible_v<U&&, T> is false.
~optional();
Effects: If is_trivially_destructible_v<T> != true and *this contains a value, calls
val->T::~T()
optional<T>& operator=(nullopt_t) noexcept;
Effects: If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no effect.
optional<T>& operator=(const optional& rhs);
Effects: See Table 35.
*this contains a value | *this does not contain a value | |
rhs contains a value | assigns *rhs to the contained value | initializes the contained value as if direct-non-list-initializing an object of type T with *rhs |
rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Remarks: If any exception is thrown, the result of the expression bool(*this) 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 shall be defined as deleted unless is_copy_constructible_v<T> is true and is_copy_assignable_v<T> is true.
optional<T>& operator=(optional&& rhs) noexcept(see below);
Effects: See Table 36. The result of the expression bool(rhs) remains unchanged.
*this contains a value | *this does not contain a value | |
rhs contains a value | assigns std::move(*rhs) to the contained value | initializes the contained value as if direct-non-list-initializing an object of type T with std::move(*rhs) |
rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Remarks: The expression inside noexcept 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 bool(*this) 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. This operator shall not participate in overload resolution unless is_move_constructible_v<T> is true and is_move_assignable_v<T> is true.
template <class U = T> optional<T>& operator=(U&& v);
Effects: If *this contains a value, assigns std::forward<U>(v) to the contained value; otherwise initializes the contained value as if direct-non-list-initializing object of type T with std::forward<U>(v).
Remarks: If any exception is thrown, the result of the expression bool(*this) 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. This function shall not participate in overload resolution unless is_same_v<optional<T>, decay_t<U>> 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.
template <class U> optional<T>& operator=(const optional<U>& rhs);
Effects: See Table 37.
*this contains a value | *this does not contain a value | |
rhs contains a value | assigns *rhs to the contained value | initializes the contained value as if direct-non-list-initializing an object of type T with *rhs |
rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Remarks: If any exception is thrown, the result of the expression bool(*this) 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. This function shall not participate in overload resolution unless
is_constructible_v<T, const U&> is true,
is_assignable_v<T&, const U&> is true,
is_constructible_v<T, optional<U>&> is false,
is_constructible_v<T, optional<U>&&> is false,
is_constructible_v<T, const optional<U>&> is false,
is_constructible_v<T, const optional<U>&&> is false,
is_convertible_v<optional<U>&, T> is false,
is_convertible_v<optional<U>&&, T> is false,
is_convertible_v<const optional<U>&, T> is false,
is_convertible_v<const optional<U>&&, T> 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.
template <class U> optional<T>& operator=(optional<U>&& rhs);
Effects: See Table 38. The result of the expression bool(rhs) remains unchanged.
*this contains a value | *this does not contain a value | |
rhs contains a value | assigns std::move(*rhs) to the contained value | initializes the contained value as if direct-non-list-initializing an object of type T with std::move(*rhs) |
rhs does not contain a value | destroys the contained value by calling val->T::~T() | no effect |
Remarks: If any exception is thrown, the result of the expression bool(*this) 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. This function shall not participate in overload resolution unless
is_constructible_v<T, U> is true,
is_assignable_v<T&, U> is true,
is_constructible_v<T, optional<U>&> is false,
is_constructible_v<T, optional<U>&&> is false,
is_constructible_v<T, const optional<U>&> is false,
is_constructible_v<T, const optional<U>&&> is false,
is_convertible_v<optional<U>&, T> is false,
is_convertible_v<optional<U>&&, T> is false,
is_convertible_v<const optional<U>&, T> is false,
is_convertible_v<const optional<U>&&, T> 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.
template <class... Args> T& emplace(Args&&... args);
Effects: Calls *this = nullopt. Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....
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> T& emplace(initializer_list<U> il, Args&&... args);
Effects: Calls *this = nullopt. Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....
void swap(optional& rhs) noexcept(see below);
Effects: See Table 39.
*this contains a value | *this does not contain a value | |
rhs contains a value | calls swap(*(*this), *rhs) | initializes the contained value of *this as if direct-non-list-initializing an object of type T with the expression 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 | initializes the contained value of rhs as if direct-non-list-initializing an object of type T with the expression std::move(*(*this)), followed by val->T::~T(); postcondition is that *this does not contain a value and rhs contains a value | no effect |
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
If any exception is thrown, the results of the expressions bool(*this) and bool(rhs) 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.
constexpr const T* operator->() const;
constexpr T* operator->();
constexpr const T& operator*() const&;
constexpr T& operator*() &;
constexpr T&& operator*() &&;
constexpr const T&& operator*() const&&;
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> constexpr T value_or(U&& v) const&;
Remarks: If is_copy_constructible_v<T> && is_convertible_v<U&&, T> is false, the program is ill-formed.
template <class U> constexpr T value_or(U&& v) &&;
Effects: Equivalent to:
return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));