// -*- 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>
   constexpr bool ranges::enable_view<optional<T>> = true;
  template<class T>
   constexpr auto format_kind<optional<T>> = range_format::disabled;

  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;
    using iterator               = implementation-defined; // see [optional.iterators]
    using const_iterator         = implementation-defined; // see [optional.iterators]

    // [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 = remove_cv_t<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 = remove_cv_t<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.iterators], iterator support
    constexpr iterator begin() noexcept;
    constexpr const_iterator begin() const noexcept;
    constexpr iterator end() noexcept;
    constexpr const_iterator end() const noexcept;

    // [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 = remove_cv_t<T>> constexpr T value_or(U &&) const &;
    template<class U = remove_cv_t<T>> 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>;

  template<class T>
  class optional<T&> { // since C++26
  public:
    using value_type     = T;
    using iterator       = implementation-defined;              // see [optional.ref.iterators]

  public:
    // [optional.ref.ctor], constructors
    constexpr optional() noexcept = default;
    constexpr optional(nullopt_t) noexcept : optional() {}
    constexpr optional(const optional& rhs) noexcept = default;

    template<class Arg>
      constexpr explicit optional(in_place_t, Arg&& arg);
    template<class U>
      constexpr explicit(see below) optional(U&& u) noexcept(see below);
    template<class U>
      constexpr explicit(see below) optional(optional<U>& rhs) noexcept(see below);
    template<class U>
      constexpr explicit(see below) optional(const optional<U>& rhs) noexcept(see below);
    template<class U>
      constexpr explicit(see below) optional(optional<U>&& rhs) noexcept(see below);
    template<class U>
      constexpr explicit(see below) optional(const optional<U>&& rhs) noexcept(see below);

    constexpr ~optional() = default;

    // [optional.ref.assign], assignment
    constexpr optional& operator=(nullopt_t) noexcept;
    constexpr optional& operator=(const optional& rhs) noexcept = default;

    template<class U> constexpr T& emplace(U&& u) noexcept(see below);

    // [optional.ref.swap], swap
    constexpr void swap(optional& rhs) noexcept;

    // [optional.ref.iterators], iterator support
    constexpr iterator begin() const noexcept;
    constexpr iterator end() const noexcept;

    // [optional.ref.observe], observers
    constexpr T*       operator->() const noexcept;
    constexpr T&       operator*() const noexcept;
    constexpr explicit operator bool() const noexcept;
    constexpr bool     has_value() const noexcept;
    constexpr T&       value() const;                           // freestanding-deleted
    template<class U = remove_cv_t<T>>
      constexpr remove_cv_t<T> value_or(U&& u) const;

    // [optional.ref.monadic], monadic operations
    template<class F> constexpr auto and_then(F&& f) const;
    template<class F> constexpr optional<invoke_result_t<F, T&>> transform(F&& f) const;
    template<class F> constexpr optional or_else(F&& f) const;

    // [optional.ref.mod], modifiers
    constexpr void reset() noexcept;

  private:
    T* val = nullptr;                                           // exposition only

    // [optional.ref.expos], exposition only helper functions
    template<class U>
      constexpr void convert-ref-init-val(U&& u);               // exposition only
  };

} // namespace std

*/

#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
#  include <__cxx03/__config>
#else
#  include <__assert>
#  include <__compare/compare_three_way_result.h>
#  include <__compare/ordering.h>
#  include <__compare/three_way_comparable.h>
#  include <__concepts/invocable.h>
#  include <__config>
#  include <__cstddef/ptrdiff_t.h>
#  include <__exception/exception.h>
#  include <__format/range_format.h>
#  include <__functional/hash.h>
#  include <__functional/invoke.h>
#  include <__functional/unary_function.h>
#  include <__fwd/functional.h>
#  include <__iterator/bounded_iter.h>
#  include <__iterator/wrap_iter.h>
#  include <__memory/addressof.h>
#  include <__memory/construct_at.h>
#  include <__ranges/enable_borrowed_range.h>
#  include <__ranges/enable_view.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/enable_if.h>
#  include <__type_traits/integral_constant.h>
#  include <__type_traits/invoke.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_core_convertible.h>
#  include <__type_traits/is_destructible.h>
#  include <__type_traits/is_function.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_same.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/reference_constructs_from_temporary.h>
#  include <__type_traits/remove_const.h>
#  include <__type_traits/remove_cv.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 <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 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;
  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
};

} // namespace std

#  if _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_optional_access() {
#    if _LIBCPP_HAS_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_;
    remove_cv_t<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_;
    remove_cv_t<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 _LIBCPP_NODEBUG = __optional_destruct_base<_Tp>;
  using value_type             = _Tp;
  using __base::__base;

  [[nodiscard]] _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_)
        static_cast<_Tp&>(this->__val_) = std::forward<_That>(__opt).__get();
    } else {
      if (this->__engaged_)
        this->reset();
      else
        __construct(std::forward<_That>(__opt).__get());
    }
  }

  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
  __swap(__optional_storage_base& __rhs) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>) {
    using std::swap;
    if (this->has_value() == __rhs.has_value()) {
      if (this->has_value())
        swap(this->__get(), __rhs.__get());
    } else {
      if (this->has_value()) {
        __rhs.__construct(std::move(this->__get()));
        this->reset();
      } else {
        this->__construct(std::move(__rhs.__get()));
        __rhs.reset();
      }
    }
  }
};

template <class _Tp>
struct __optional_storage_base<_Tp, true> {
  using value_type                 = _Tp;
  using __raw_type _LIBCPP_NODEBUG = remove_reference_t<_Tp>;
  __raw_type* __value_;

  _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}

  template <class _Up>
  _LIBCPP_HIDE_FROM_ABI constexpr void __convert_init_ref_val(_Up&& __val) noexcept {
    _Tp& __r(std::forward<_Up>(__val));
    __value_ = std::addressof(__r);
  }

  template <class _UArg>
  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) {
    static_assert(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                  "Attempted to construct a reference element in optional from a "
                  "possible temporary");
    __convert_init_ref_val(std::forward<_UArg>(__uarg));
  }

  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }

  [[nodiscard]] _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_; }

  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(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                  "Attempted to construct a reference element in tuple from a "
                  "possible temporary");
    __convert_init_ref_val(std::forward<_UArg>(__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());
    }
  }

  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap(__optional_storage_base& __rhs) noexcept {
    std::swap(__value_, __rhs.__value_);
  }
};

template <class _Tp, bool = is_trivially_copy_constructible_v<_Tp> || is_lvalue_reference_v<_Tp>>
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_v<_Tp> || is_lvalue_reference_v<_Tp>>
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_v<_Tp> && is_trivially_copy_constructible_v<_Tp> &&
                  is_trivially_copy_assignable_v<_Tp>) ||
                 is_lvalue_reference_v<_Tp>>
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_v<_Tp> && is_trivially_move_constructible_v<_Tp> &&
                  is_trivially_move_assignable_v<_Tp>) ||
                 is_lvalue_reference_v<_Tp>>
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 _LIBCPP_NODEBUG =
    __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >;

template <class _Tp>
using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
    __sfinae_assign_base< (is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Tp>) || is_lvalue_reference_v<_Tp>,
                          (is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp>) || is_lvalue_reference_v<_Tp>>;

template <class _Tp>
class optional;

#    if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
template <class _Tp>
constexpr bool ranges::enable_view<optional<_Tp>> = true;

template <class _Tp>
constexpr range_format format_kind<optional<_Tp>> = range_format::disabled;

template <class _Tp>
constexpr bool ranges::enable_borrowed_range<optional<_Tp&>> = true;

#    endif

#    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... _Args>
inline constexpr bool __is_constructible_for_optional_v = is_constructible_v<_Tp, _Args...>;

template <class _Tp, class... _Args>
struct __is_constructible_for_optional : bool_constant<__is_constructible_for_optional_v<_Tp, _Args...>> {};

template <class _Tp, class _Up, class... _Args>
inline constexpr bool __is_constructible_for_optional_initializer_list_v =
    is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>;

#    if _LIBCPP_STD_VER >= 26
template <class _Tp, class... _Args>
inline constexpr bool __is_constructible_for_optional_v<_Tp&, _Args...> = false;
template <class _Tp, class _Arg>
inline constexpr bool __is_constructible_for_optional_v<_Tp&, _Arg> =
    is_constructible_v<_Tp&, _Arg> && !reference_constructs_from_temporary_v<_Tp&, _Arg>;

template <class _Tp, class _Up, class... _Args>
inline constexpr bool __is_constructible_for_optional_initializer_list_v<_Tp&, _Up, _Args...> = false;
#    endif

template <class _Tp, class = void>
struct __optional_iterator {};

#    if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR

template <class _Tp>
struct __optional_iterator<_Tp, enable_if_t<is_object_v<_Tp>>> {
private:
  using __pointer _LIBCPP_NODEBUG       = add_pointer_t<_Tp>;
  using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;

public:
#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
  using iterator       = __bounded_iter<__wrap_iter<__pointer>>;
  using const_iterator = __bounded_iter<__wrap_iter<__const_pointer>>;
#      else
  using iterator       = __wrap_iter<__pointer>;
  using const_iterator = __wrap_iter<__const_pointer>;
#      endif

  // [optional.iterators], iterator support
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() noexcept {
    auto& __derived_self = static_cast<optional<_Tp>&>(*this);
    auto* __ptr          = std::addressof(__derived_self.__get());

#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
    return std::__make_bounded_iter(
        __wrap_iter<__pointer>(__ptr),
        __wrap_iter<__pointer>(__ptr),
        __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
#      else
    return iterator(__ptr);
#      endif
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept {
    auto& __derived_self = static_cast<const optional<_Tp>&>(*this);
    auto* __ptr          = std::addressof(__derived_self.__get());

#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
    return std::__make_bounded_iter(
        __wrap_iter<__const_pointer>(__ptr),
        __wrap_iter<__const_pointer>(__ptr),
        __wrap_iter<__const_pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
#      else
    return const_iterator(__ptr);
#      endif
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() noexcept {
    return begin() + (static_cast<optional<_Tp>&>(*this).has_value() ? 1 : 0);
  }
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept {
    return begin() + (static_cast<const optional<_Tp>&>(*this).has_value() ? 1 : 0);
  }
};

template <class _Tp>
struct __optional_iterator<_Tp&, enable_if_t<is_object_v<_Tp> && !__is_unbounded_array_v<_Tp> >> {
private:
  using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;

public:
#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
  using iterator = __bounded_iter<__wrap_iter<__pointer>>;
#      else
  using iterator = __wrap_iter<__pointer>;
#      endif

  // [optional.ref.iterators], iterator support

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const noexcept {
    auto& __derived_self = static_cast<const optional<_Tp&>&>(*this);
    auto* __ptr          = __derived_self.has_value() ? std::addressof(__derived_self.__get()) : nullptr;

#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
    return std::__make_bounded_iter(
        __wrap_iter<__pointer>(__ptr),
        __wrap_iter<__pointer>(__ptr),
        __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
#      else
    return iterator(__ptr);
#      endif
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const noexcept {
    return begin() + (static_cast<const optional<_Tp&>&>(*this).has_value() ? 1 : 0);
  }
};

#    endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR

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>,
      public __optional_iterator<_Tp> {
  using __base _LIBCPP_NODEBUG = __optional_move_assign_base<_Tp>;

public:
  using value_type = __libcpp_remove_reference_t<_Tp>;

  using __trivially_relocatable _LIBCPP_NODEBUG =
      conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;

private:
  static_assert(!is_same_v<__remove_cvref_t<_Tp>, in_place_t>,
                "instantiation of optional with in_place_t is ill-formed");
  static_assert(!is_same_v<__remove_cvref_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
#    if _LIBCPP_STD_VER >= 26
  static_assert(!is_rvalue_reference_v<_Tp>, "instantiation of optional with an rvalue reference type is ill-formed");
#    else
  static_assert(!is_reference_v<_Tp>, "instantiation of optional with a reference type is ill-formed");
#    endif
  static_assert(is_destructible_v<_Tp>, "instantiation of optional with a non-destructible type is ill-formed");
  static_assert(!is_array_v<_Tp>, "instantiation of optional with an array type is ill-formed");

#    if _LIBCPP_STD_VER >= 26
  template <class _Up>
  constexpr static bool __libcpp_opt_ref_ctor_deleted =
      is_lvalue_reference_v<_Tp> && reference_constructs_from_temporary_v<_Tp, _Up>;

  template <class _Up>
  constexpr static bool __ref_ctor_enabled =
      is_lvalue_reference_v<_Tp> && !reference_constructs_from_temporary_v<_Tp, _Up>;
#    endif

  // 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 _LIBCPP_NODEBUG =
      _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 _LIBCPP_NODEBUG =
        _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 _LIBCPP_NODEBUG =
        _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 _LIBCPP_NODEBUG =
      _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
           _CheckOptionalLikeConstructor<_QualUp>,
           __check_tuple_constructor_fail >;
  template <class _Up, class _QualUp>
  using _CheckOptionalLikeAssign _LIBCPP_NODEBUG =
      _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,
      enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>, __is_constructible_for_optional<_Tp, _Args...>>::value, int> = 0>
  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
      : __base(in_place, std::forward<_Args>(__args)...) {}

  template <class _Up,
            class... _Args,
            enable_if_t<__is_constructible_for_optional_initializer_list_v<_Tp, _Up, _Args...>, int> = 0>
  _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 = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
#    endif
      : __base(in_place, std::forward<_Up>(__v)) {
  }

  template <class _Up                                                                        = remove_cv_t<_Tp>,
            enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
#    endif
      : __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)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, const _Up&>)
#    endif
  {
    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)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, const _Up&>)
#    endif
  {
    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)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
#    endif
  {
    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)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
#    endif
  {
    this->__construct_from(std::move(__v));
  }

  // deleted optional<T&> constructors and additional optional<T&> constructors
#    if _LIBCPP_STD_VER >= 26
  // optional(U&&)
  template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
    requires __libcpp_opt_ref_ctor_deleted<_Up>
  optional(_Up&&) = delete;

  template <class _Up                                                                        = remove_cv_t<_Tp>,
            enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
    requires __libcpp_opt_ref_ctor_deleted<_Up>
  explicit optional(_Up&&) = delete;

  // optional(optional<U>& rhs)
  template <class _Up>
    requires __ref_ctor_enabled<_Up&> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) &&
             is_constructible_v<_Tp&, _Up&>
  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
      optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
    this->__construct_from(__rhs);
  }

  template <class _Up>
    requires __libcpp_opt_ref_ctor_deleted<_Up&> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
                 (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
  constexpr explicit optional(optional<_Up>& __rhs) noexcept = delete;

  // optional(const optional<U>&)
  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
    requires __libcpp_opt_ref_ctor_deleted<const _Up&>
  optional(const optional<_Up>&) = delete;

  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
    requires __libcpp_opt_ref_ctor_deleted<const _Up&>
  explicit optional(const optional<_Up>&) = delete;

  // optional(optional<U>&&)
  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
    requires __libcpp_opt_ref_ctor_deleted<_Up>
  optional(optional<_Up>&&) = delete;

  template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
    requires __libcpp_opt_ref_ctor_deleted<_Up>
  explicit optional(optional<_Up>&&) = delete;

  // optional(const optional<U>&&)
  template <class _Up>
    requires __ref_ctor_enabled<const _Up> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
             (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up>
  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v<const _Up, _Tp&>)
      optional(const optional<_Up>&& __v) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) {
    this->__construct_from(std::move(__v));
  }

  template <class _Up>
    requires __libcpp_opt_ref_ctor_deleted<const _Up> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
                 (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up>
  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>&& __v) noexcept = delete;
#    endif

#    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        = remove_cv_t<_Tp>,
            enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
                             _Or<_IsNotSame<__remove_cvref_t<_Up>, _Tp>, _Not<is_scalar<_Tp>>>,
                             is_constructible<_Tp, _Up>,
                             is_assignable<_Tp&, _Up>,
                             is_object<_Tp>>::value,
                        int> = 0>
  _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, enable_if_t<__is_constructible_for_optional_v<_Tp, _Args...>, int> = 0>
  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args)
#    if _LIBCPP_STD_VER >= 26
      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp, _Args...>)
#    endif
  {
    reset();
    this->__construct(std::forward<_Args>(__args)...);
    return this->__get();
  }

  template <class _Up,
            class... _Args,
            enable_if_t<__is_constructible_for_optional_initializer_list_v<_Tp, _Up, _Args...>, int> = 0>
  _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<_Tp> && is_nothrow_swappable_v<_Tp>)
#    if _LIBCPP_STD_VER >= 26
      || is_lvalue_reference_v<_Tp>
#    endif
  ) {
    this->__swap(__opt);
  }

  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    _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<_Tp> operator->() noexcept
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
    return std::addressof(this->__get());
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
    return this->__get();
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
    return this->__get();
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
    return std::move(this->__get());
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    _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;

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& value() const&
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    if (!this->has_value())
      std::__throw_bad_optional_access();
    return this->__get();
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() &
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    if (!this->has_value())
      std::__throw_bad_optional_access();
    return this->__get();
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() &&
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    if (!this->has_value())
      std::__throw_bad_optional_access();
    return std::move(this->__get());
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&&
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  {
    if (!this->has_value())
      std::__throw_bad_optional_access();
    return std::move(this->__get());
  }

  template <class _Up = remove_cv_t<_Tp>>
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
    static_assert(is_copy_constructible_v<_Tp>, "optional<T>::value_or: T must be copy constructible");
    static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
    return this->has_value() ? this->__get() : static_cast<_Tp>(std::forward<_Up>(__v));
  }

  template <class _Up = remove_cv_t<_Tp>>
#    if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#    endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
    static_assert(is_move_constructible_v<_Tp>, "optional<T>::value_or: T must be move constructible");
    static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
    return this->has_value() ? std::move(this->__get()) : static_cast<_Tp>(std::forward<_Up>(__v));
  }

#    if _LIBCPP_STD_VER >= 23
  template <class _Func>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
    using _Up = invoke_result_t<_Func, _Tp&>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
    using _Up = invoke_result_t<_Func, const _Tp&>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
    using _Up = invoke_result_t<_Func, _Tp&&>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
    using _Up = invoke_result_t<_Func, const _Tp&&>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
    using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
    using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
    using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
    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>
#      if _LIBCPP_STD_VER >= 26
    requires(is_object_v<_Tp>)
#      endif
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
    using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
    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>
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
    requires is_copy_constructible_v<_Tp>
#      if _LIBCPP_STD_VER >= 26
             && (is_object_v<_Tp>)
#      endif
  {
    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>
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
    requires is_move_constructible_v<_Tp>
#      if _LIBCPP_STD_VER >= 26
             && (is_object_v<_Tp>)
#      endif
  {
    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;

// optional<T&> overloads
#    if _LIBCPP_STD_VER >= 26

  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() const noexcept
    requires(is_lvalue_reference_v<_Tp>)
  {
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
    return std::addressof(this->__get());
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() const noexcept
    requires(is_lvalue_reference_v<_Tp>)
  {
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
    return this->__get();
  }

  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() const
    requires(is_lvalue_reference_v<_Tp>)
  {
    if (!this->has_value())
      std::__throw_bad_optional_access();
    return this->__get();
  }

  template <class _Up = remove_cvref_t<_Tp>>
    requires(is_lvalue_reference_v<_Tp> && is_object_v<__libcpp_remove_reference_t<_Tp>> &&
             !is_array_v<__libcpp_remove_reference_t<_Tp>>)
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decay_t<_Tp> value_or(_Up&& __v) const {
    static_assert(
        is_constructible_v<remove_cvref_t<_Tp>, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
    static_assert(
        is_convertible_v<_Up, remove_cvref_t<_Tp>>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
    return this->has_value() ? this->__get() : static_cast<remove_cvref_t<_Tp>>(std::forward<_Up>(__v));
  }

  template <class _Func>
    requires(is_lvalue_reference_v<_Tp>)
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const {
    using _Up = invoke_result_t<_Func, _Tp&>;
    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>
    requires(is_lvalue_reference_v<_Tp>)
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional<remove_cv_t<invoke_result_t<_Func, _Tp&>>>
  transform(_Func&& __f) const {
    using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>;
    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 <invocable _Func>
    requires(is_lvalue_reference_v<_Tp>)
  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const {
    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)();
  }
#    endif
};

template <class _Tp>
optional(_Tp) -> optional<_Tp>;

// [optional.relops] Relational operators

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr 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,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr 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,
           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
                       int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr 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,
           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
                       int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr 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,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr 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,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr 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

// [optional.nullops] Comparison 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

// [optional.comp.with.t] Comparison with T

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, const _Up& __v) {
  if (__x.has_value())
    return *__x == __v;
  return false;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __v, const optional<_Up>& __x) {
  if (__x.has_value())
    return __v == *__x;
  return false;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, const _Up& __v) {
  if (__x.has_value())
    return *__x != __v;
  return true;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __v, const optional<_Up>& __x) {
  if (__x.has_value())
    return __v != *__x;
  return true;
}

template < class _Tp,
           class _Up,
           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
                       int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>& __x, const _Up& __v) {
  if (__x.has_value())
    return *__x < __v;
  return true;
}

template < class _Tp,
           class _Up,
           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
                       int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __v, const optional<_Up>& __x) {
  if (__x.has_value())
    return __v < *__x;
  return false;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, const _Up& __v) {
  if (__x.has_value())
    return *__x <= __v;
  return true;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __v, const optional<_Up>& __x) {
  if (__x.has_value())
    return __v <= *__x;
  return false;
}

template < class _Tp,
           class _Up,
           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
                       int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, const _Up& __v) {
  if (__x.has_value())
    return *__x > __v;
  return false;
}

template < class _Tp,
           class _Up,
           enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
                       int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __v, const optional<_Up>& __x) {
  if (__x.has_value())
    return __v > *__x;
  return true;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>& __x, const _Up& __v) {
  if (__x.has_value())
    return *__x >= __v;
  return false;
}

template <
    class _Tp,
    class _Up,
    enable_if_t<__is_core_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
                int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __v, const optional<_Up>& __x) {
  if (__x.has_value())
    return __v >= *__x;
  return 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, enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) {
  __x.swap(__y);
}

struct __make_optional_barrier_tag {
  explicit __make_optional_barrier_tag() = default;
};

template <
#    if _LIBCPP_STD_VER >= 26
    __make_optional_barrier_tag = __make_optional_barrier_tag{},
#    endif
    class _Tp,
    enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>, int> = 0>
[[nodiscard]] _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, enable_if_t<__is_constructible_for_optional_v<_Tp, _Args...>, int> = 0>
[[nodiscard]] _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,
          enable_if_t<__is_constructible_for_optional_initializer_list_v<_Tp, _Up, _Args...>, int> = 0>
[[nodiscard]] _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 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

  [[nodiscard]] _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 // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)

#endif // _LIBCPP_OPTIONAL
