В этом подпункте описывается шаблон класса optional , представляющий необязательные объекты. An optional object - это объект, который содержит хранилище для другого объекта и управляет временем жизни этого содержащегося объекта, если таковой имеется. Содержащийся объект может быть инициализирован после инициализации необязательного объекта и может быть уничтожен до того, как необязательный объект будет уничтожен. Состояние инициализации содержащегося объекта отслеживается необязательным объектом.
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>>; }
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 указывает на содержащееся значение.
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
Remarks: Никакое содержащееся значение не инициализируется. Для каждого типа объекта T эти конструкторы должны быть constexpr constructors.
constexpr optional(const optional& rhs);
Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка *rhs.
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) без изменений.
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)....
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)....
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).
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.
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) без изменений.
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.
~optional();
Effects: Если is_trivially_destructible_v<T> != true и *this содержит значение, вызывает
val->T::~T()
optional<T>& operator=(nullopt_t) noexcept;
Effects: Если *this содержит значение, вызывает val->T::~T() уничтожение содержащегося значения; в остальном никакого эффекта.
optional<T>& operator=(const optional& rhs);
Effects: См. Таблицу 35.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает *rhs содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
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) остается неизменным.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает std::move(*rhs) содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std::move(*rhs) |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
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).
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.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает *rhs содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
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) остается неизменным.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает std::move(*rhs) содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std::move(*rhs) |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
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);
Effects: Звонки *this = nullopt. Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std::forward<Args>(args)....
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)....
void swap(optional& rhs) noexcept(see below);
Effects: См. Таблицу 39.
*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 содержит значение | нет эффекта |
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конструктора перемещения.
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: Если 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));
struct nullopt_t{see below};
inline constexpr nullopt_t nullopt(unspecified);
Структура nullopt_t - это пустой тип структуры, используемый как уникальный тип для обозначения состояния отсутствия значения для optional объектов. В частности, optional<T> имеет конструктор с nullopt_t одним аргументом; это указывает на то, что должен быть создан необязательный объект, не содержащий значения.
class bad_optional_access : public exception { public: bad_optional_access(); };
Класс bad_optional_access определяет тип объектов, создаваемых как исключения, чтобы сообщить о ситуации, когда делается попытка получить доступ к значению необязательного объекта, не содержащего значения.
bad_optional_access();
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.
Remarks: Специализации этого шаблона функции, для которого *x < *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x > *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
Remarks: Специализации этого шаблона функции, для которого *x > *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x <= *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
Remarks: Специализации этого шаблона функции, для которого *x <= *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x >= *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
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;
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;
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;
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;
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;
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;
template <class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
Requires: Выражение *x == v должно быть правильно сформированным, а его результат должен быть преобразован в bool. [ Note: T не должно быть EqualityComparable. ] — end note
template <class T, class U> constexpr bool operator==(const U& v, const optional<T>& x);
Requires: Выражение v == *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
Requires: Выражение *x != v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator!=(const U& v, const optional<T>& x);
Requires: Выражение v != *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
Requires: Выражение *x < v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<(const U& v, const optional<T>& x);
Requires: Выражение v < *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
Requires: Выражение *x <= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<=(const U& v, const optional<T>& x);
Requires: Выражение v <= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
Requires: Выражение *x > v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>(const U& v, const optional<T>& x);
Requires: Выражение v > *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
Requires: Выражение *x >= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>=(const U& v, const optional<T>& x);
Requires: Выражение v >= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(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);
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);
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.