23 General utilities library [utilities]

23.6 Optional objects [optional]

23.6.1 In general [optional.general]

В этом подпункте описывается шаблон класса optional , представляющий необязательные объекты. An optional object - это объект, который содержит хранилище для другого объекта и управляет временем жизни этого содержащегося объекта, если таковой имеется. Содержащийся объект может быть инициализирован после инициализации необязательного объекта и может быть уничтожен до того, как необязательный объект будет уничтожен. Состояние инициализации содержащегося объекта отслеживается необязательным объектом.

23.6.2 Header <optional> synopsis [optional.syn]

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

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

  // [optional.bad.access], class bad_­optional_­access
  class bad_optional_access;

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

  // [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, class U> constexpr bool operator==(const optional<T>&, const U&);
  template <class T, class U> constexpr bool operator==(const U&, const optional<T>&);
  template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
  template <class T, class U> constexpr bool operator!=(const U&, const optional<T>&);
  template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
  template <class T, class U> constexpr bool operator<(const U&, const optional<T>&);
  template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
  template <class T, class U> constexpr bool operator<=(const U&, const optional<T>&);
  template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
  template <class T, class U> constexpr bool operator>(const U&, const optional<T>&);
  template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
  template <class T, class U> constexpr bool operator>=(const U&, 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>>;
}

Программа, которая требует создания экземпляра шаблона optional для ссылочного типа или, возможно, для типов с квалификацией cv, in_­place_­t или nullopt_­t плохо сформирована.

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

Любой экземпляр optional<T> в любой момент времени либо содержит значение, либо не содержит значения. Когда является экземпляром optional<T> contains a value, это означает, что объект типа T, называемый необязательным объектом contained value, размещается в хранилище необязательного объекта. Реализациям не разрешается использовать дополнительное хранилище, такое как динамическая память, для выделения содержащегося в нем значения. Содержимое значение должно быть размещено в области optional<T> памяти, соответствующей типу T. Когда объект типа optional<T> контекстно преобразуется в bool, преобразование возвращается, true если объект содержит значение; в противном случае преобразование вернется false.

Участник val предназначен только для экспозиции. Когда optional<T> объект содержит значение, val указывает на содержащееся значение.

T должен быть типом объекта и удовлетворять требованиям Destructible.

23.6.3.1 Constructors [optional.ctor]

constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;

Postconditions: *this не содержит значения.

Remarks: Никакое содержащееся значение не инициализируется. Для каждого типа объекта T эти конструкторы должны быть constexpr constructors.

constexpr optional(const optional& rhs);

Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка *rhs.

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

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Этот конструктор должен быть определен как удален , если is_­copy_­constructible_­v<T> не true. Если is_­trivially_­copy_­constructible_­v<T> есть true, этот конструктор должен быть constexpr конструктором.

constexpr optional(optional&& rhs) noexcept(see below);

Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка std​::​move(*rhs). bool(rhs) без изменений.

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

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Выражение внутри noexcept эквивалентно is_­nothrow_­move_­constructible_­v<T>. Этот конструктор не должен участвовать в разрешении перегрузки , если is_­move_­constructible_­v<T> не true. Если is_­trivially_­move_­constructible_­v<T> есть true, этот конструктор должен быть constexpr конструктором.

template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Если Tконструктор, выбранный для инициализации, является конструктором constexpr, этот конструктор должен быть конструктором constexpr. Этот конструктор не должен участвовать в разрешении перегрузки , если is_­constructible_­v<T, Args...> не true.

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

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами il, std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­constructible_­v<T, initializer_­list<U>&, Args&&...> не true. Если Tконструктор, выбранный для инициализации, является конструктором constexpr, этот конструктор должен быть конструктором constexpr.

[ Note: Следующие конструкторы условно указаны как явные. Обычно это реализуется путем объявления двух таких конструкторов, максимум один из которых участвует в разрешении перегрузки. ]end note

template <class U = T> EXPLICIT constexpr optional(U&& v);

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую, не являясь списком, T с выражением std​::​forward<U>(v).

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Если Tвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr. Этот конструктор не должен участвовать в разрешении перегрузки, за исключением случаев, когда is_­constructible_­v<T, U&&> есть true, is_­same_­v<decay_­t<U>, in_­place_­t> есть falseи is_­same_­v<optional<T>, decay_­t<U>> есть false. Конструктор является явным тогда и только тогда, когда он is_­convertible_­v<U&&, T> есть false.

template <class U> EXPLICIT optional(const optional<U>& rhs);

Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка *rhs.

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

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если только

  • is_­constructible_­v<T, const U&> есть true,

  • is_­constructible_­v<T, optional<U>&> есть false,

  • is_­constructible_­v<T, optional<U>&&> есть false,

  • is_­constructible_­v<T, const optional<U>&> есть false,

  • is_­constructible_­v<T, const optional<U>&&> есть false,

  • is_­convertible_­v<optional<U>&, T> есть false,

  • is_­convertible_­v<optional<U>&&, T> есть false,

  • is_­convertible_­v<const optional<U>&, T> есть false, и

  • is_­convertible_­v<const optional<U>&&, T> есть false.

Конструктор является явным тогда и только тогда, когда он is_­convertible_­v<const U&, T> есть false.

template <class U> EXPLICIT optional(optional<U>&& rhs);

Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка std​::​move(*rhs). bool(rhs) без изменений.

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

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если только

  • is_­constructible_­v<T, U&&> правда,

  • is_­constructible_­v<T, optional<U>&> есть false,

  • is_­constructible_­v<T, optional<U>&&> есть false,

  • is_­constructible_­v<T, const optional<U>&> есть false,

  • is_­constructible_­v<T, const optional<U>&&> есть false,

  • is_­convertible_­v<optional<U>&, T> есть false,

  • is_­convertible_­v<optional<U>&&, T> есть false,

  • is_­convertible_­v<const optional<U>&, T> есть false, и

  • is_­convertible_­v<const optional<U>&&, T> есть false.

Конструктор является явным тогда и только тогда, когда он is_­convertible_­v<U&&, T> есть false.

23.6.3.2 Destructor [optional.dtor]

~optional();

Effects: Если is_­trivially_­destructible_­v<T> != true и *this содержит значение, вызывает

val->T::~T()

Remarks: Если is_­trivially_­destructible_­v<T> == true тогда этот деструктор должен быть тривиальным деструктором.

23.6.3.3 Assignment [optional.assign]

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

Effects: Если *this содержит значение, вызывает val->T​::​~T() уничтожение содержащегося значения; в остальном никакого эффекта.

Returns: *this.

Postconditions: *this не содержит значения.

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

Effects: См. Таблицу 35.

Таблица 35 - optional​::​operator=(const optional&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает *rhs содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

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

Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора копирования возникает исключение , никакого эффекта. Если во время вызова Tприсваивания копии возникает исключение , состояние содержащегося в нем значения определяется гарантией безопасности исключений Tприсваивания копии. Этот оператор должен быть определен как удален , если is_­copy_­constructible_­v<T> не true и is_­copy_­assignable_­v<T> является true.

optional<T>& operator=(optional&& rhs) noexcept(see below);

Effects: См. Таблицу 36. Результат выражения bool(rhs) остается неизменным.

Таблица 36 - optional​::​operator=(optional&&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает std​::​move(*rhs) содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std​::​move(*rhs)
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

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

Remarks: Выражение внутри noexcept эквивалентно:

is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>

Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора перемещения возникает исключение , состояние *rhs.val определяется гарантией безопасности исключений Tконструктора перемещения. Если во время вызова Tприсваивания перемещения возникает исключение , состояние *val и *rhs.val определяется гарантией безопасности исключения Tприсваивания перемещения. Этот оператор не должен участвовать в разрешении перегрузки , если is_­move_­constructible_­v<T> не true и is_­move_­assignable_­v<T> является true.

template <class U = T> optional<T>& operator=(U&& v);

Effects: Если *this содержит значение, присваивается std​::​forward<U>(v) содержащемуся значению; в противном случае инициализирует значение , содержащееся как если прямой не-список-инициализацию объекта типа T с std​::​forward<U>(v).

Returns: *this.

Postconditions: *this содержит значение.

Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора возникает исключение , состояние v определяется гарантией безопасности исключений Tконструктора. Если во время вызова Tприсваивания вызывается исключение , состояние *val и v определяется гарантией безопасности исключений Tприсваивания. Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда is_­same_­v<optional<T>, decay_­t<U>> есть false, conjunction_­v<is_­scalar<T>, is_­same<T, decay_­t<U>>> есть false, is_­constructible_­v<T, U> есть trueи is_­assignable_­v<T&, U> есть true.

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

Effects: См. Таблицу 37.

Таблица 37 - optional​::​operator=(const optional<U>&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает *rhs содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

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

Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора возникает исключение , состояние *rhs.val определяется гарантией безопасности исключений Tконструктора. Если во время вызова Tприсваивания вызывается исключение , состояние *val и *rhs.val определяется гарантией безопасности исключений Tприсваивания. Эта функция не должна участвовать в разрешении перегрузки, если только

  • is_­constructible_­v<T, const U&> есть true,

  • is_­assignable_­v<T&, const U&> есть true,

  • is_­constructible_­v<T, optional<U>&> есть false,

  • is_­constructible_­v<T, optional<U>&&> есть false,

  • is_­constructible_­v<T, const optional<U>&> есть false,

  • is_­constructible_­v<T, const optional<U>&&> есть false,

  • is_­convertible_­v<optional<U>&, T> есть false,

  • is_­convertible_­v<optional<U>&&, T> есть false,

  • is_­convertible_­v<const optional<U>&, T> есть false,

  • is_­convertible_­v<const optional<U>&&, T> есть false,

  • is_­assignable_­v<T&, optional<U>&> есть false,

  • is_­assignable_­v<T&, optional<U>&&> есть false,

  • is_­assignable_­v<T&, const optional<U>&> есть false, и

  • is_­assignable_­v<T&, const optional<U>&&> есть false.

template <class U> optional<T>& operator=(optional<U>&& rhs);

Effects: См. Таблицу 38. Результат выражения bool(rhs) остается неизменным.

Таблица 38 - optional​::​operator=(optional<U>&&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает std​::​move(*rhs) содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std​::​move(*rhs)
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

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

Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора возникает исключение , состояние *rhs.val определяется гарантией безопасности исключений Tконструктора. Если во время вызова Tприсваивания вызывается исключение , состояние *val и *rhs.val определяется гарантией безопасности исключений Tприсваивания. Эта функция не должна участвовать в разрешении перегрузки, если только

  • is_­constructible_­v<T, U> есть true,

  • is_­assignable_­v<T&, U> есть true,

  • is_­constructible_­v<T, optional<U>&> есть false,

  • is_­constructible_­v<T, optional<U>&&> есть false,

  • is_­constructible_­v<T, const optional<U>&> есть false,

  • is_­constructible_­v<T, const optional<U>&&> есть false,

  • is_­convertible_­v<optional<U>&, T> есть false,

  • is_­convertible_­v<optional<U>&&, T> есть false,

  • is_­convertible_­v<const optional<U>&, T> есть false,

  • is_­convertible_­v<const optional<U>&&, T> есть false,

  • is_­assignable_­v<T&, optional<U>&> есть false,

  • is_­assignable_­v<T&, optional<U>&&> есть false,

  • is_­assignable_­v<T&, const optional<U>&> есть false, и

  • is_­assignable_­v<T&, const optional<U>&&> есть false.

template <class... Args> T& emplace(Args&&... args);

Requires: is_­constructible_­v<T, Args&&...> есть true.

Effects: Звонки *this = nullopt. Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Если во время вызова Tконструктора возникает исключение , *this не содержит значения, а предыдущее *val (если оно есть) было уничтожено.

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

Effects: Звонки *this = nullopt. Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами il, std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Если во время вызова Tконструктора возникает исключение , *this не содержит значения, а предыдущее *val (если оно есть) было уничтожено. Эта функция не будет участвовать в разрешении перегрузки , если is_­constructible_­v<T, initializer_­list<U>&, Args&&...> не true.

23.6.3.4 Swap [optional.swap]

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

Requires: Lvalues ​​типа T должны быть заменяемыми и is_­move_­constructible_­v<T> есть true.

Effects: См. Таблицу 39.

Таблица 39 - optional​::​swap(optional&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение звонки swap(*(*this), *rhs) инициализирует содержащееся значение, *this как если бы напрямую без списка инициализирует объект типа T с выражением std​::​move(*rhs), за которым следует rhs.val->T​::​~T(); постусловие - это то, что *this содержит значение и rhs не содержит значения
rhs не содержит значения инициализирует содержащееся значение, rhs как если бы напрямую без списка инициализирует объект типа T с выражением std​::​move(*(*this)), за которым следует val->T​::​~T(); постусловие - это то, *this что не содержит значения и rhs содержит значение нет эффекта

Throws: Любые исключения, вызванные операциями в соответствующей части таблицы 39.

Remarks: Выражение внутри noexcept эквивалентно:

is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>

Если возникает какое-либо исключение, результаты выражений bool(*this) и bool(rhs) остаются неизменными. Если во время вызова функции возникает исключение swap, состояние *val и *rhs.val определяется гарантией безопасности исключений swap для lvalues T. Если во время вызова Tконструктора перемещения возникает исключение , состояние *val и *rhs.val определяется гарантией безопасности исключений Tконструктора перемещения.

23.6.3.5 Observers [optional.observe]

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

Requires: *this содержит значение.

Returns: val.

Throws: Ничего такого.

Remarks: Эти функции должны быть функциями constexpr.

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

Requires: *this содержит значение.

Returns: *val.

Throws: Ничего такого.

Remarks: Эти функции должны быть функциями constexpr.

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

Requires: *this содержит значение.

Effects: Эквивалентен: return std​::​move(*val);

constexpr explicit operator bool() const noexcept;

Returns: true тогда и только тогда, когда *this содержит значение.

Remarks: Эта функция должна быть функцией constexpr.

constexpr bool has_value() const noexcept;

Returns: true тогда и только тогда, когда *this содержит значение.

Remarks: Эта функция должна быть функцией constexpr.

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

Effects: Эквивалентен:

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

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

Effects: Эквивалентен:

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

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

Effects: Эквивалентен:

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

Remarks: Если is_­copy_­constructible_­v<T> && is_­convertible_­v<U&&, T> есть false, программа сформирована неправильно.

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

Effects: Эквивалентен:

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

Remarks: Если is_­move_­constructible_­v<T> && is_­convertible_­v<U&&, T> есть false, программа сформирована неправильно.

23.6.3.6 Modifiers [optional.mod]

void reset() noexcept;

Effects: Если *this содержит значение, вызывает val->T​::​~T() уничтожение содержащегося значения; в остальном никакого эффекта.

Postconditions: *this не содержит значения.

23.6.4 No-value state indicator [optional.nullopt]

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

Структура nullopt_­t - это пустой тип структуры, используемый как уникальный тип для обозначения состояния отсутствия значения для optional объектов. В частности, optional<T> имеет конструктор с nullopt_­t одним аргументом; это указывает на то, что должен быть создан необязательный объект, не содержащий значения.

Тип nullopt_­t не должен иметь конструктора по умолчанию или конструктора списка инициализаторов и не должен быть агрегатом.

23.6.5 Class bad_­optional_­access [optional.bad.access]

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

Класс bad_­optional_­access определяет тип объектов, создаваемых как исключения, чтобы сообщить о ситуации, когда делается попытка получить доступ к значению необязательного объекта, не содержащего значения.

bad_optional_access();

Effects: Создает объект класса bad_­optional_­access.

Postconditions: what() возвращает определяемый реализацией файл ntbs .

23.6.6 Relational operators [optional.relops]

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

Requires: Выражение *x == *y должно быть правильно сформированным, а его результат должен быть преобразован в bool. [ Note: T не должно быть EqualityComparable. ] end note

Returns: Если bool(x) != bool(y), false; в противном случае bool(x) == false, если true,; иначе *x == *y.

Remarks: Специализации этого шаблона функции, для которого *x == *y является выражением константы ядра, должны быть функциями constexpr.

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

Requires: Выражение *x != *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Returns: Если bool(x) != bool(y), true; в противном случае, если bool(x) == false, false; иначе *x != *y.

Remarks: Специализации этого шаблона функции, для которого *x != *y является выражением константы ядра, должны быть функциями constexpr.

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

Requires: *x < *y должен быть правильно сформирован, и его результат должен быть преобразован в bool.

Returns: Если !y, false; в противном случае, если !x, true; иначе *x < *y.

Remarks: Специализации этого шаблона функции, для которого *x < *y является выражением константы ядра, должны быть функциями constexpr.

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

Requires: Выражение *x > *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Returns: Если !x, false; в противном случае, если !y, true; иначе *x > *y.

Remarks: Специализации этого шаблона функции, для которого *x > *y является выражением константы ядра, должны быть функциями constexpr.

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

Requires: Выражение *x <= *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Returns: Если !x, true; в противном случае, если !y, false; иначе *x <= *y.

Remarks: Специализации этого шаблона функции, для которого *x <= *y является выражением константы ядра, должны быть функциями constexpr.

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

Requires: Выражение *x >= *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Returns: Если !y, true; в противном случае, если !x, false; иначе *x >= *y.

Remarks: Специализации этого шаблона функции, для которого *x >= *y является выражением константы ядра, должны быть функциями constexpr.

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

23.6.8 Comparison with T [optional.comp_with_t]

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

Requires: Выражение *x == v должно быть правильно сформированным, а его результат должен быть преобразован в bool. [ Note: T не должно быть EqualityComparable. ]end note

Effects: Эквивалентен: return bool(x) ? *x == v : false;

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

Requires: Выражение v == *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? v == *x : false;

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

Requires: Выражение *x != v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? *x != v : true;

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

Requires: Выражение v != *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? v != *x : true;

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

Requires: Выражение *x < v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? *x < v : true;

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

Requires: Выражение v < *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? v < *x : false;

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

Requires: Выражение *x <= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? *x <= v : true;

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

Requires: Выражение v <= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? v <= *x : false;

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

Requires: Выражение *x > v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? *x > v : false;

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

Requires: Выражение v > *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? v > *x : true;

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

Requires: Выражение *x >= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? *x >= v : false;

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

Requires: Выражение v >= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентен: return bool(x) ? v >= *x : true;

23.6.9 Specialized algorithms [optional.specalg]

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

Effects: Звонки x.swap(y).

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_­move_­constructible_­v<T> не true и is_­swappable_­v<T> является 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: Эквивалентен: 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: Эквивалентен: return optional<T>(in_­place, il, std​::​forward<Args>(args)...);

23.6.10 Hash support [optional.hash]

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

Специализация hash<optional<T>> включена ([unord.hash]) тогда и только тогда, когда hash<remove_­const_­t<T>> она включена. Когда включено, для объекта o типа optional<T>if bool(o) == true, then hash<optional<T>>()(o) должно оцениваться с тем же значением, что и hash<remove_­const_­t<T>>()(*o); в противном случае он принимает неопределенное значение. Функции-члены не гарантируются noexcept.