Files
clang-p2996/libcxx/include/__cxx03/optional
Nikolas Klauser e78f53d1e8 Reapply "[libc++][C++03] Copy the LLVM 19 headers (#108999)" (#112127)
This reverts commit 68c04b0ae6.

This disables the IWYU mapping that caused the failure, since
the headers aren't reachable for now.

This is the first part of the "Freezing C++03 headers" proposal
explained in
https://discourse.llvm.org/t/rfc-freezing-c-03-headers-in-libc/77319/58.

This patch mechanically copies the headers as of the LLVM 19.1 release
into a subdirectory of libc++ so that we can start using these headers
when building in C++03 mode. We are going to be backporting important
changes to that copy of the headers until the LLVM 21 release. After the
LLVM 21 release, only critical bugfixes will be fixed in the C++03 copy
of the headers.

This patch only performs a copy of the headers -- these headers are
still unused by the rest of the codebase.
2024-10-24 00:17:37 +02:00

1305 lines
52 KiB
C++

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_OPTIONAL
#define _LIBCPP_OPTIONAL
/*
optional synopsis
// C++1z
namespace std {
// [optional.optional], class template optional
template <class T>
class optional;
template<class T>
concept is-derived-from-optional = requires(const T& t) { // exposition only
[]<class U>(const optional<U>&){ }(t);
};
// [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>&);
template<class T, three_way_comparable_with<T> U>
constexpr compare_three_way_result_t<T, U>
operator<=>(const optional<T>&, const optional<U>&); // since C++20
// [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; // until C++17
template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17
template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17
template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; // until C++17
template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; // until C++17
template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17
template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17
template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; // until C++17
template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; // until C++17
template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17
template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17
template<class T>
constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // since C++20
// [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 T&, const optional<U>&);
template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator<(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator<(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator>(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator>(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
template<class T, class U>
requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U>
constexpr compare_three_way_result_t<T, U>
operator<=>(const optional<T>&, const U&); // since C++20
// [optional.specalg], specialized algorithms
template<class T>
void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
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>
constexpr explicit(see-below) optional(U &&);
template<class U>
explicit(see-below) optional(const optional<U> &); // constexpr in C++20
template<class U>
explicit(see-below) optional(optional<U> &&); // constexpr in C++20
// [optional.dtor], destructor
~optional(); // constexpr in C++20
// [optional.assign], assignment
optional &operator=(nullopt_t) noexcept; // constexpr in C++20
constexpr optional &operator=(const optional &);
constexpr optional &operator=(optional &&) noexcept(see below);
template<class U = T> optional &operator=(U &&); // constexpr in C++20
template<class U> optional &operator=(const optional<U> &); // constexpr in C++20
template<class U> optional &operator=(optional<U> &&); // constexpr in C++20
template<class... Args> T& emplace(Args &&...); // constexpr in C++20
template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
// [optional.swap], swap
void swap(optional &) noexcept(see below ); // constexpr in C++20
// [optional.observe], observers
constexpr T const *operator->() const noexcept;
constexpr T *operator->() noexcept;
constexpr T const &operator*() const & noexcept;
constexpr T &operator*() & noexcept;
constexpr T &&operator*() && noexcept;
constexpr const T &&operator*() const && noexcept;
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr T const &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.monadic], monadic operations
template<class F> constexpr auto and_then(F&& f) &; // since C++23
template<class F> constexpr auto and_then(F&& f) &&; // since C++23
template<class F> constexpr auto and_then(F&& f) const&; // since C++23
template<class F> constexpr auto and_then(F&& f) const&&; // since C++23
template<class F> constexpr auto transform(F&& f) &; // since C++23
template<class F> constexpr auto transform(F&& f) &&; // since C++23
template<class F> constexpr auto transform(F&& f) const&; // since C++23
template<class F> constexpr auto transform(F&& f) const&&; // since C++23
template<class F> constexpr optional or_else(F&& f) &&; // since C++23
template<class F> constexpr optional or_else(F&& f) const&; // since C++23
// [optional.mod], modifiers
void reset() noexcept; // constexpr in C++20
private:
T *val; // exposition only
};
template<class T>
optional(T) -> optional<T>;
} // namespace std
*/
#include <__assert>
#include <__compare/compare_three_way_result.h>
#include <__compare/three_way_comparable.h>
#include <__concepts/invocable.h>
#include <__config>
#include <__exception/exception.h>
#include <__functional/hash.h>
#include <__functional/invoke.h>
#include <__functional/unary_function.h>
#include <__fwd/functional.h>
#include <__memory/addressof.h>
#include <__memory/construct_at.h>
#include <__tuple/sfinae_helpers.h>
#include <__type_traits/add_pointer.h>
#include <__type_traits/conditional.h>
#include <__type_traits/conjunction.h>
#include <__type_traits/decay.h>
#include <__type_traits/disjunction.h>
#include <__type_traits/is_array.h>
#include <__type_traits/is_assignable.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/is_destructible.h>
#include <__type_traits/is_nothrow_assignable.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/is_object.h>
#include <__type_traits/is_reference.h>
#include <__type_traits/is_scalar.h>
#include <__type_traits/is_swappable.h>
#include <__type_traits/is_trivially_assignable.h>
#include <__type_traits/is_trivially_constructible.h>
#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/is_trivially_relocatable.h>
#include <__type_traits/negation.h>
#include <__type_traits/remove_const.h>
#include <__type_traits/remove_cvref.h>
#include <__type_traits/remove_reference.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <__utility/in_place.h>
#include <__utility/move.h>
#include <__utility/swap.h>
#include <__verbose_abort>
#include <initializer_list>
#include <new>
#include <version>
// standard-mandated includes
// [optional.syn]
#include <compare>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
namespace std // purposefully not using versioning namespace
{
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public exception {
public:
_LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT = default;
_LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT = default;
_LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default;
// Get the key function ~bad_optional_access() into the dylib
~bad_optional_access() _NOEXCEPT override;
const char* what() const _NOEXCEPT override;
};
} // namespace std
#if _LIBCPP_STD_VER >= 17
_LIBCPP_BEGIN_NAMESPACE_STD
_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS void
__throw_bad_optional_access() {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
throw bad_optional_access();
# else
_LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode");
# endif
}
struct nullopt_t {
struct __secret_tag {
explicit __secret_tag() = default;
};
_LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
};
inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
struct __optional_construct_from_invoke_tag {};
template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
struct __optional_destruct_base;
template <class _Tp>
struct __optional_destruct_base<_Tp, false> {
typedef _Tp value_type;
static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
union {
char __null_state_;
value_type __val_;
};
bool __engaged_;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() {
if (__engaged_)
__val_.~value_type();
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
: __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
# if _LIBCPP_STD_VER >= 23
template <class _Fp, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(
__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
: __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
# endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
if (__engaged_) {
__val_.~value_type();
__engaged_ = false;
}
}
};
template <class _Tp>
struct __optional_destruct_base<_Tp, true> {
typedef _Tp value_type;
static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
union {
char __null_state_;
value_type __val_;
};
bool __engaged_;
_LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
: __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
# if _LIBCPP_STD_VER >= 23
template <class _Fp, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(
__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
: __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
# endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
if (__engaged_) {
__engaged_ = false;
}
}
};
template <class _Tp, bool = is_reference<_Tp>::value>
struct __optional_storage_base : __optional_destruct_base<_Tp> {
using __base = __optional_destruct_base<_Tp>;
using value_type = _Tp;
using __base::__base;
_LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; }
_LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; }
_LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; }
_LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); }
_LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); }
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) {
_LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...);
this->__engaged_ = true;
}
template <class _That>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
if (__opt.has_value())
__construct(std::forward<_That>(__opt).__get());
}
template <class _That>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
if (this->__engaged_ == __opt.has_value()) {
if (this->__engaged_)
this->__val_ = std::forward<_That>(__opt).__get();
} else {
if (this->__engaged_)
this->reset();
else
__construct(std::forward<_That>(__opt).__get());
}
}
};
// optional<T&> is currently required to be ill-formed. However, it may
// be allowed in the future. For this reason, it has already been implemented
// to ensure we can make the change in an ABI-compatible manner.
template <class _Tp>
struct __optional_storage_base<_Tp, true> {
using value_type = _Tp;
using __raw_type = remove_reference_t<_Tp>;
__raw_type* __value_;
template <class _Up>
static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
using _RawUp = __libcpp_remove_reference_t<_Up>;
using _UpPtr = _RawUp*;
using _RawTp = __libcpp_remove_reference_t<_Tp>;
using _TpPtr = _RawTp*;
using _CheckLValueArg =
integral_constant<bool,
(is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) ||
is_same<_RawUp, reference_wrapper<_RawTp>>::value ||
is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value >;
return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) ||
(is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
is_convertible<_UpPtr, _TpPtr>::value);
}
_LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}
template <class _UArg>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
: __value_(std::addressof(__uarg)) {
static_assert(__can_bind_reference<_UArg>(),
"Attempted to construct a reference element in tuple from a "
"possible temporary");
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
_LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; }
_LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; }
_LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); }
template <class _UArg>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) {
_LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
static_assert(__can_bind_reference<_UArg>(),
"Attempted to construct a reference element in tuple from a "
"possible temporary");
__value_ = std::addressof(__val);
}
template <class _That>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
if (__opt.has_value())
__construct(std::forward<_That>(__opt).__get());
}
template <class _That>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
if (has_value() == __opt.has_value()) {
if (has_value())
*__value_ = std::forward<_That>(__opt).__get();
} else {
if (has_value())
reset();
else
__construct(std::forward<_That>(__opt).__get());
}
}
};
template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
struct __optional_copy_base : __optional_storage_base<_Tp> {
using __optional_storage_base<_Tp>::__optional_storage_base;
};
template <class _Tp>
struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> {
using __optional_storage_base<_Tp>::__optional_storage_base;
_LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) {
this->__construct_from(__opt);
}
_LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&) = default;
_LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default;
_LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&) = default;
};
template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
struct __optional_move_base : __optional_copy_base<_Tp> {
using __optional_copy_base<_Tp>::__optional_copy_base;
};
template <class _Tp>
struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> {
using value_type = _Tp;
using __optional_copy_base<_Tp>::__optional_copy_base;
_LIBCPP_HIDE_FROM_ABI __optional_move_base() = default;
_LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
__optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) {
this->__construct_from(std::move(__opt));
}
_LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default;
_LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&) = default;
};
template <class _Tp,
bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value &&
is_trivially_copy_assignable<_Tp>::value>
struct __optional_copy_assign_base : __optional_move_base<_Tp> {
using __optional_move_base<_Tp>::__optional_move_base;
};
template <class _Tp>
struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> {
using __optional_move_base<_Tp>::__optional_move_base;
_LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base() = default;
_LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
_LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base&
operator=(const __optional_copy_assign_base& __opt) {
this->__assign_from(__opt);
return *this;
}
_LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
};
template <class _Tp,
bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value &&
is_trivially_move_assignable<_Tp>::value>
struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
};
template <class _Tp>
struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> {
using value_type = _Tp;
using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
_LIBCPP_HIDE_FROM_ABI __optional_move_assign_base() = default;
_LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
_LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&) = default;
_LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base&
operator=(__optional_move_assign_base&& __opt) noexcept(
is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) {
this->__assign_from(std::move(__opt));
return *this;
}
};
template <class _Tp>
using __optional_sfinae_ctor_base_t =
__sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >;
template <class _Tp>
using __optional_sfinae_assign_base_t =
__sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
(is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >;
template <class _Tp>
class optional;
# if _LIBCPP_STD_VER >= 20
template <class _Tp>
concept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); };
# endif // _LIBCPP_STD_VER >= 20
template <class _Tp>
struct __is_std_optional : false_type {};
template <class _Tp>
struct __is_std_optional<optional<_Tp>> : true_type {};
template <class _Tp>
class _LIBCPP_DECLSPEC_EMPTY_BASES optional
: private __optional_move_assign_base<_Tp>,
private __optional_sfinae_ctor_base_t<_Tp>,
private __optional_sfinae_assign_base_t<_Tp> {
using __base = __optional_move_assign_base<_Tp>;
public:
using value_type = _Tp;
using __trivially_relocatable = conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
private:
// Disable the reference extension using this static assert.
static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,
"instantiation of optional with in_place_t is ill-formed");
static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>,
"instantiation of optional with nullopt_t is ill-formed");
static_assert(!is_reference_v<value_type>, "instantiation of optional with a reference type is ill-formed");
static_assert(is_destructible_v<value_type>, "instantiation of optional with a non-destructible type is ill-formed");
static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed");
// LWG2756: conditionally explicit conversion from _Up
struct _CheckOptionalArgsConstructor {
template <class _Up>
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
}
template <class _Up>
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
}
};
template <class _Up>
using _CheckOptionalArgsCtor =
_If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
(!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value),
_CheckOptionalArgsConstructor,
__check_tuple_constructor_fail >;
template <class _QualUp>
struct _CheckOptionalLikeConstructor {
template <class _Up, class _Opt = optional<_Up>>
using __check_constructible_from_opt =
_Or< is_constructible<_Tp, _Opt&>,
is_constructible<_Tp, _Opt const&>,
is_constructible<_Tp, _Opt&&>,
is_constructible<_Tp, _Opt const&&>,
is_convertible<_Opt&, _Tp>,
is_convertible<_Opt const&, _Tp>,
is_convertible<_Opt&&, _Tp>,
is_convertible<_Opt const&&, _Tp> >;
template <class _Up, class _Opt = optional<_Up>>
using __check_assignable_from_opt =
_Or< is_assignable<_Tp&, _Opt&>,
is_assignable<_Tp&, _Opt const&>,
is_assignable<_Tp&, _Opt&&>,
is_assignable<_Tp&, _Opt const&&> >;
template <class _Up, class _QUp = _QualUp>
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
return is_convertible<_QUp, _Tp>::value &&
(is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
}
template <class _Up, class _QUp = _QualUp>
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
return !is_convertible<_QUp, _Tp>::value &&
(is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
}
template <class _Up, class _QUp = _QualUp>
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
// Construction and assignability of _QUp to _Tp has already been
// checked.
return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value;
}
};
template <class _Up, class _QualUp>
using _CheckOptionalLikeCtor =
_If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
_CheckOptionalLikeConstructor<_QualUp>,
__check_tuple_constructor_fail >;
template <class _Up, class _QualUp>
using _CheckOptionalLikeAssign =
_If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,
_CheckOptionalLikeConstructor<_QualUp>,
__check_tuple_constructor_fail >;
public:
_LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
_LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {}
template <
class _InPlaceT,
class... _Args,
class = enable_if_t< _And< _IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...> >::value > >
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
: __base(in_place, std::forward<_Args>(__args)...) {}
template <class _Up,
class... _Args,
class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> >
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
: __base(in_place, __il, std::forward<_Args>(__args)...) {}
template <class _Up = value_type,
enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
template <class _Up, enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
// LWG2756: conditionally explicit conversion from const optional<_Up>&
template <class _Up,
enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
this->__construct_from(__v);
}
template <class _Up,
enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
this->__construct_from(__v);
}
// LWG2756: conditionally explicit conversion from optional<_Up>&&
template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
this->__construct_from(std::move(__v));
}
template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
this->__construct_from(std::move(__v));
}
# if _LIBCPP_STD_VER >= 23
template <class _Tag,
class _Fp,
class... _Args,
__enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
: __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
# endif
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept {
reset();
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default;
// LWG2756
template <
class _Up = value_type,
class = enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Up>, optional>,
_Or< _IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>> >,
is_constructible<value_type, _Up>,
is_assignable<value_type&, _Up> >::value> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
if (this->has_value())
this->__get() = std::forward<_Up>(__v);
else
this->__construct(std::forward<_Up>(__v));
return *this;
}
// LWG2756
template <class _Up,
enable_if_t< _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
this->__assign_from(__v);
return *this;
}
// LWG2756
template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
this->__assign_from(std::move(__v));
return *this;
}
template <class... _Args, class = enable_if_t< is_constructible_v<value_type, _Args...> > >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
reset();
this->__construct(std::forward<_Args>(__args)...);
return this->__get();
}
template <class _Up,
class... _Args,
class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...> > >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
reset();
this->__construct(__il, std::forward<_Args>(__args)...);
return this->__get();
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<value_type> && is_nothrow_swappable_v<value_type>) {
if (this->has_value() == __opt.has_value()) {
using std::swap;
if (this->has_value())
swap(this->__get(), __opt.__get());
} else {
if (this->has_value()) {
__opt.__construct(std::move(this->__get()));
reset();
} else {
this->__construct(std::move(__opt.__get()));
__opt.reset();
}
}
}
_LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
return std::addressof(this->__get());
}
_LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
return std::addressof(this->__get());
}
_LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
return this->__get();
}
_LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
return this->__get();
}
_LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
return std::move(this->__get());
}
_LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
return std::move(this->__get());
}
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); }
using __base::__get;
using __base::has_value;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const& value() const& {
if (!this->has_value())
__throw_bad_optional_access();
return this->__get();
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& value() & {
if (!this->has_value())
__throw_bad_optional_access();
return this->__get();
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& value() && {
if (!this->has_value())
__throw_bad_optional_access();
return std::move(this->__get());
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const&& value() const&& {
if (!this->has_value())
__throw_bad_optional_access();
return std::move(this->__get());
}
template <class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) const& {
static_assert(is_copy_constructible_v<value_type>, "optional<T>::value_or: T must be copy constructible");
static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T");
return this->has_value() ? this->__get() : static_cast<value_type>(std::forward<_Up>(__v));
}
template <class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) && {
static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible");
static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T");
return this->has_value() ? std::move(this->__get()) : static_cast<value_type>(std::forward<_Up>(__v));
}
# if _LIBCPP_STD_VER >= 23
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) & {
using _Up = invoke_result_t<_Func, value_type&>;
static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
"Result of f(value()) must be a specialization of std::optional");
if (*this)
return std::invoke(std::forward<_Func>(__f), value());
return remove_cvref_t<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) const& {
using _Up = invoke_result_t<_Func, const value_type&>;
static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
"Result of f(value()) must be a specialization of std::optional");
if (*this)
return std::invoke(std::forward<_Func>(__f), value());
return remove_cvref_t<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) && {
using _Up = invoke_result_t<_Func, value_type&&>;
static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
"Result of f(std::move(value())) must be a specialization of std::optional");
if (*this)
return std::invoke(std::forward<_Func>(__f), std::move(value()));
return remove_cvref_t<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
using _Up = invoke_result_t<_Func, const value_type&&>;
static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
"Result of f(std::move(value())) must be a specialization of std::optional");
if (*this)
return std::invoke(std::forward<_Func>(__f), std::move(value()));
return remove_cvref_t<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) & {
using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
if (*this)
return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
return optional<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const& {
using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
if (*this)
return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
return optional<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) && {
using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
if (*this)
return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
return optional<_Up>();
}
template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const&& {
using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
if (*this)
return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
return optional<_Up>();
}
template <invocable _Func>
_LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
requires is_copy_constructible_v<value_type>
{
static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
"Result of f() should be the same type as this optional");
if (*this)
return *this;
return std::forward<_Func>(__f)();
}
template <invocable _Func>
_LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
requires is_move_constructible_v<value_type>
{
static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
"Result of f() should be the same type as this optional");
if (*this)
return std::move(*this);
return std::forward<_Func>(__f)();
}
# endif // _LIBCPP_STD_VER >= 23
using __base::reset;
};
# if _LIBCPP_STD_VER >= 17
template <class _Tp>
optional(_Tp) -> optional<_Tp>;
# endif
// Comparisons between optionals
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
bool >
operator==(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return false;
if (!static_cast<bool>(__x))
return true;
return *__x == *__y;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
bool >
operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return true;
if (!static_cast<bool>(__x))
return false;
return *__x != *__y;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
bool >
operator<(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__y))
return false;
if (!static_cast<bool>(__x))
return true;
return *__x < *__y;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
bool >
operator>(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__x))
return false;
if (!static_cast<bool>(__y))
return true;
return *__x > *__y;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
bool >
operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__x))
return true;
if (!static_cast<bool>(__y))
return false;
return *__x <= *__y;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
bool >
operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__y))
return true;
if (!static_cast<bool>(__x))
return false;
return *__x >= *__y;
}
# if _LIBCPP_STD_VER >= 20
template <class _Tp, three_way_comparable_with<_Tp> _Up>
_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (__x && __y)
return *__x <=> *__y;
return __x.has_value() <=> __y.has_value();
}
# endif // _LIBCPP_STD_VER >= 20
// Comparisons with nullopt
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept {
return !static_cast<bool>(__x);
}
# if _LIBCPP_STD_VER <= 17
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept {
return !static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept {
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept {
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept {
return false;
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept {
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept {
return !static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept {
return true;
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept {
return static_cast<bool>(__x);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept {
return false;
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept {
return true;
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept {
return !static_cast<bool>(__x);
}
# else // _LIBCPP_STD_VER <= 17
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept {
return __x.has_value() <=> false;
}
# endif // _LIBCPP_STD_VER <= 17
// Comparisons with T
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
bool >
operator==(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x == __v : false;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
bool >
operator==(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v == *__x : false;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
bool >
operator!=(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x != __v : true;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
bool >
operator!=(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v != *__x : true;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
bool >
operator<(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x < __v : true;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
bool >
operator<(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v < *__x : false;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
bool >
operator<=(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x <= __v : true;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
bool >
operator<=(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v <= *__x : false;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
bool >
operator>(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x > __v : false;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
bool >
operator>(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v > *__x : true;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
bool >
operator>=(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x >= __v : false;
}
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
bool >
operator>=(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v >= *__x : true;
}
# if _LIBCPP_STD_VER >= 20
template <class _Tp, class _Up>
requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up>
_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
operator<=>(const optional<_Tp>& __x, const _Up& __v) {
return __x.has_value() ? *__x <=> __v : strong_ordering::less;
}
# endif // _LIBCPP_STD_VER >= 20
template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void >
swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) {
__x.swap(__y);
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI constexpr optional<decay_t<_Tp>> make_optional(_Tp&& __v) {
return optional<decay_t<_Tp>>(std::forward<_Tp>(__v));
}
template <class _Tp, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(_Args&&... __args) {
return optional<_Tp>(in_place, std::forward<_Args>(__args)...);
}
template <class _Tp, class _Up, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) {
return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...);
}
template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > {
# if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
_LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
_LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
# endif
_LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const {
return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
}
};
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 17
_LIBCPP_POP_MACROS
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
# include <atomic>
# include <climits>
# include <concepts>
# include <ctime>
# include <iterator>
# include <limits>
# include <memory>
# include <ratio>
# include <stdexcept>
# include <tuple>
# include <type_traits>
# include <typeinfo>
# include <utility>
# include <variant>
#endif
#endif // _LIBCPP_OPTIONAL