20 General utilities library [utilities]

20.6 Optional objects [optional]

20.6.1 In general [optional.general]

This subclause describes class template optional that represents optional objects. An optional object is an object that contains the storage for another object and manages the lifetime of this contained object, if any. The contained object may be initialized after the optional object has been initialized, and may be destroyed before the optional object has been destroyed. The initialization state of the contained object is tracked by the optional object.

20.6.2 Header <optional> synopsis [optional.syn]

namespace std {
  // [optional.optional], optional
  template <class T> class optional;

  // [optional.nullopt], no-value state indicator
  struct nullopt_t{see below};
  constexpr nullopt_t nullopt(unspecified);

  // [optional.bad.access], class bad_optional_access
  class bad_optional_access;

  // [optional.relops], relational operators
  template <class T>
  constexpr bool operator==(const optional<T>&, const optional<T>&);
  template <class T>
  constexpr bool operator!=(const optional<T>&, const optional<T>&);
  template <class T>
  constexpr bool operator<(const optional<T>&, const optional<T>&);
  template <class T>
  constexpr bool operator>(const optional<T>&, const optional<T>&);
  template <class T>
  constexpr bool operator<=(const optional<T>&, const optional<T>&);
  template <class T>
  constexpr bool operator>=(const optional<T>&, const optional<T>&);

  // [optional.nullops], comparison with nullopt
  template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
  template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
  template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
  template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
  template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
  template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
  template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
  template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
  template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
  template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
  template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
  template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;

  // [optional.comp_with_t], comparison with T
  template <class T> constexpr bool operator==(const optional<T>&, const T&);
  template <class T> constexpr bool operator==(const T&, const optional<T>&);
  template <class T> constexpr bool operator!=(const optional<T>&, const T&);
  template <class T> constexpr bool operator!=(const T&, const optional<T>&);
  template <class T> constexpr bool operator<(const optional<T>&, const T&);
  template <class T> constexpr bool operator<(const T&, const optional<T>&);
  template <class T> constexpr bool operator<=(const optional<T>&, const T&);
  template <class T> constexpr bool operator<=(const T&, const optional<T>&);
  template <class T> constexpr bool operator>(const optional<T>&, const T&);
  template <class T> constexpr bool operator>(const T&, const optional<T>&);
  template <class T> constexpr bool operator>=(const optional<T>&, const T&);
  template <class T> constexpr bool operator>=(const T&, const optional<T>&);

  // [optional.specalg], specialized algorithms
  template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
  template <class T> constexpr optional<see below> make_optional(T&&);
  template <class T, class... Args>
    constexpr optional<T> make_optional(Args&&... args);
  template <class T, class U, class... Args>
    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);

  // [optional.hash], hash support
  template <class T> struct hash;
  template <class T> struct hash<optional<T>>;
}

A program that necessitates the instantiation of template optional for a reference type, or for possibly cv-qualified types in_place_t or nullopt_t is ill-formed.

20.6.3 Class template optional [optional.optional]

template <class T> class optional {
public:
  using value_type = T;

  // [optional.ctor], constructors
  constexpr optional() noexcept;
  constexpr optional(nullopt_t) noexcept;
  optional(const optional&);
  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> void emplace(Args&&...);
  template <class U, class... Args>
    void 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
};

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.

T shall be an object type and shall satisfy the requirements of Destructible (Table [tab:destructible]).

20.6.3.1 Constructors [optional.ctor]

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 shall be constexpr constructors ([dcl.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.

Postconditions: bool(rhs) == bool(*this).

Throws: Any exception thrown by the selected constructor of T.

Remarks: This constructor shall be defined as deleted unless is_copy_constructible_v<T> is true.

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.

Postconditions: bool(rhs) == bool(*this).

Throws: Any exception thrown by the selected constructor of T.

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.

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)....

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 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)....

Postconditions: *this contains a value.

Throws: Any exception thrown by the selected constructor of T.

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).

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 shall be a constexpr constructor. This constructor shall not participate in overload resolution unless is_constructible_v<T, U&&> is true, is_same_v<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.

Postconditions: bool(rhs) == bool(*this).

Throws: Any exception thrown by the selected constructor of T.

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.

Postconditions: bool(rhs) == bool(*this).

Throws: Any exception thrown by the selected constructor of T.

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.

20.6.3.2 Destructor [optional.dtor]

~optional();

Effects: If is_trivially_destructible_v<T> != true and *this contains a value, calls val->T::~T().

Remarks: If is_trivially_destructible_v<T> == true then this destructor shall be a trivial destructor.

20.6.3.3 Assignment [optional.assign]

optional<T>& operator=(nullopt_t) noexcept;

Effects: If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no effect.

Returns: *this.

Postconditions: *this does not contain a value.

optional<T>& operator=(const optional& rhs);

Effects: See Table [tab:optional.assign.copy].

Table 35optional::operator=(const optional&) effects
*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

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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 [tab:optional.assign.move]. The result of the expression bool(rhs) remains unchanged.

Table 36optional::operator=(optional&&) effects
*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

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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).

Returns: *this.

Postconditions: *this contains a value.

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 [tab:optional.assign.copy.templ].

Table 37optional::operator=(const optional<U>&) effects
*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

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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 [tab:optional.assign.move.templ]. The result of the expression bool(rhs) remains unchanged.

Table 38optional::operator=(optional<U>&&) effects
*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

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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> void emplace(Args&&... args);

Requires: is_constructible_v<T, Args&&...> is true.

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)....

Postconditions: *this contains a 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> void 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)....

Postconditions: *this contains a 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. This function shall not participate in overload resolution unless is_constructible_v<T, initializer_list<U>&, Args&&...> is true.

20.6.3.4 Swap [optional.swap]

void swap(optional& rhs) noexcept(see below);

Requires: Lvalues of type T shall be swappable and is_move_constructible_v<T> is true.

Effects: See Table [tab:optional.swap].

Table 39optional::swap(optional&) effects
*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

Throws: Any exceptions thrown by the operations in the relevant part of Table [tab:optional.swap].

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.

20.6.3.5 Observers [optional.observe]

constexpr const T* operator->() const; constexpr T* operator->();

Requires: *this contains a value.

Returns: val.

Throws: Nothing.

Remarks: These functions shall be constexpr functions.

constexpr const T& operator*() const&; constexpr T& operator*() &;

Requires: *this contains a value.

Returns: *val.

Throws: Nothing.

Remarks: These functions shall be constexpr functions.

constexpr T&& operator*() &&; constexpr const T&& operator*() const&&;

Requires: *this contains a value.

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 shall be a constexpr function.

constexpr bool has_value() const noexcept;

Returns: true if and only if *this contains a value.

Remarks: This function shall be a constexpr function.

constexpr const T& value() const&; constexpr T& value() &;

Effects: Equivalent to:

return bool(*this) ? *val : throw bad_optional_access();

constexpr T&& value() &&; constexpr const T&& value() const&&;

Effects: Equivalent to:

return bool(*this) ? std::move(*val) : throw bad_optional_access();

template <class U> constexpr T value_or(U&& v) const&;

Effects: Equivalent to:

return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));

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));

Remarks: If is_move_constructible_v<T> && is_convertible_v<U&&, T> is false, the program is ill-formed.

20.6.3.6 Modifiers [optional.mod]

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.

20.6.4 No-value state indicator [optional.nullopt]

struct nullopt_t{see below}; constexpr nullopt_t nullopt(unspecified);

The struct nullopt_t is an empty structure type used as a unique type to indicate the state of not containing a value for optional objects. In particular, optional<T> has a constructor with nullopt_t as a single argument; this indicates that an optional object not containing a value shall be constructed.

Type nullopt_t shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate.

20.6.5 Class bad_optional_access [optional.bad.access]

class bad_optional_access : public logic_error {
public:
  bad_optional_access();
};

The class bad_optional_access defines the type of objects thrown as exceptions to report the situation where an attempt is made to access the value of an optional object that does not contain a value.

bad_optional_access();

Effects: Constructs an object of class bad_optional_access.

Postconditions: what() returns an implementation-defined ntbs.

20.6.6 Relational operators [optional.relops]

template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y);

Requires: The expression *x == *y shall be well-formed and its result shall be convertible to bool. [ Note: T need not be EqualityComparable.  — end note ]

Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true; otherwise *x == *y.

Remarks: Specializations of this function template for which *x == *y is a core constant expression shall be constexpr functions.

template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y);

Requires: The expression *x != *y shall be well-formed and its result shall be convertible to bool.

Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; otherwise *x != *y.

Remarks: Specializations of this function template for which *x != *y is a core constant expression shall be constexpr functions.

template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y);

Requires: *x < *y shall be well-formed and its result shall be convertible to bool.

Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.

Remarks: Specializations of this function template for which *x < *y is a core constant expression shall be constexpr functions.

template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y);

Requires: The expression *x > *y shall be well-formed and its result shall be convertible to bool.

Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.

Remarks: Specializations of this function template for which *x > *y is a core constant expression shall be constexpr functions.

template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y);

Requires: The expression *x <= *y shall be well-formed and its result shall be convertible to bool.

Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.

Remarks: Specializations of this function template for which *x <= *y is a core constant expression shall be constexpr functions.

template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y);

Requires: The expression *x >= *y shall be well-formed and its result shall be convertible to bool.

Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.

Remarks: Specializations of this function template for which *x >= *y is a core constant expression shall be constexpr functions.

20.6.7 Comparison with nullopt [optional.nullops]

template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept; template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept;

Returns: !x.

template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept; template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept;

Returns: bool(x).

template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept;

Returns: false.

template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept;

Returns: bool(x).

template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept;

Returns: !x.

template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept;

Returns: true.

template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept;

Returns: bool(x).

template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept;

Returns: false.

template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept;

Returns: true.

template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept;

Returns: !x.

20.6.8 Comparison with T [optional.comp_with_t]

template <class T> constexpr bool operator==(const optional<T>& x, const T& v);

Effects: Equivalent to: return bool(x) ? *x == v : false;

template <class T> constexpr bool operator==(const T& v, const optional<T>& x);

Effects: Equivalent to: return bool(x) ? v == *x : false;

template <class T> constexpr bool operator!=(const optional<T>& x, const T& v);

Effects: Equivalent to: return bool(x) ? *x != v : true;

template <class T> constexpr bool operator!=(const T& v, const optional<T>& x);

Effects: Equivalent to: return bool(x) ? v != *x : true;

template <class T> constexpr bool operator<(const optional<T>& x, const T& v);

Effects: Equivalent to: return bool(x) ? *x < v : true;

template <class T> constexpr bool operator<(const T& v, const optional<T>& x);

Effects: Equivalent to: return bool(x) ? v < *x : false;

template <class T> constexpr bool operator<=(const optional<T>& x, const T& v);

Effects: Equivalent to: return bool(x) ? *x <= v : true;

template <class T> constexpr bool operator<=(const T& v, const optional<T>& x);

Effects: Equivalent to: return bool(x) ? v <= *x : false;

template <class T> constexpr bool operator>(const optional<T>& x, const T& v);

Effects: Equivalent to: return bool(x) ? *x > v : false;

template <class T> constexpr bool operator>(const T& v, const optional<T>& x);

Effects: Equivalent to: return bool(x) ? v > *x : true;

template <class T> constexpr bool operator>=(const optional<T>& x, const T& v);

Effects: Equivalent to: return bool(x) ? *x >= v : false;

template <class T> constexpr bool operator>=(const T& v, const optional<T>& x);

Effects: Equivalent to: return bool(x) ? v >= *x : true;

20.6.9 Specialized algorithms [optional.specalg]

template <class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));

Effects: Calls x.swap(y).

Remarks: This function shall not participate in overload resolution unless is_move_constructible_v<T> is true and is_swappable_v<T> is true.

template <class T> constexpr optional<decay_t<T>> make_optional(T&& v);

Returns: optional<decay_t<T>>(std::forward<T>(v)).

template <class T, class...Args> constexpr optional<T> make_optional(Args&&... args);

Effects: Equivalent to: return optional<T>(in_place, std::forward<Args>(args)...);

template <class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);

Effects: Equivalent to: return optional<T>(in_place, il, std::forward<Args>(args)...);

20.6.10 Hash support [optional.hash]

template <class T> struct hash<optional<T>>;

The specialization hash<optional<T>> is enabled ([unord.hash]) if and only if hash<remove_const_t<T>> is enabled. When enabled, for an object o of type optional<T>, if bool(o) == true, then hash<optional<T>>()(o) shall evaluate to the same value as hash<remove_const_t<T>>()(*o); otherwise it evaluates to an unspecified value.