23 General utilities library [utilities]

23.6 Optional objects [optional]

23.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;
    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.

T shall be an object type and shall satisfy the requirements of Destructible.

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

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

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

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

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.

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

23.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 35.

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 36. 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 37.

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 38. 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> T& 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.

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

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. This function shall not participate in overload resolution unless is_­constructible_­v<T, initializer_­list<U>&, Args&&...> is true.

23.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 39.

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

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.

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

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