xref: /freebsd/contrib/llvm-project/libcxx/include/optional (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_OPTIONAL
110b57cec5SDimitry Andric#define _LIBCPP_OPTIONAL
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    optional synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric// C++1z
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricnamespace std {
19*06c3fb27SDimitry Andric  // [optional.optional], class template optional
20*06c3fb27SDimitry Andric  template <class T>
21*06c3fb27SDimitry Andric    class optional;
220b57cec5SDimitry Andric
23*06c3fb27SDimitry Andric  template<class T>
24*06c3fb27SDimitry Andric    concept is-derived-from-optional = requires(const T& t) {       // exposition only
25*06c3fb27SDimitry Andric      []<class U>(const optional<U>&){ }(t);
26*06c3fb27SDimitry Andric    };
27*06c3fb27SDimitry Andric
28*06c3fb27SDimitry Andric  // [optional.nullopt], no-value state indicator
290b57cec5SDimitry Andric  struct nullopt_t{see below };
300b57cec5SDimitry Andric  inline constexpr nullopt_t nullopt(unspecified );
310b57cec5SDimitry Andric
32*06c3fb27SDimitry Andric  // [optional.bad.access], class bad_optional_access
330b57cec5SDimitry Andric  class bad_optional_access;
340b57cec5SDimitry Andric
35*06c3fb27SDimitry Andric  // [optional.relops], relational operators
360b57cec5SDimitry Andric  template <class T, class U>
370b57cec5SDimitry Andric    constexpr bool operator==(const optional<T>&, const optional<U>&);
380b57cec5SDimitry Andric  template <class T, class U>
390b57cec5SDimitry Andric    constexpr bool operator!=(const optional<T>&, const optional<U>&);
400b57cec5SDimitry Andric  template <class T, class U>
410b57cec5SDimitry Andric    constexpr bool operator<(const optional<T>&, const optional<U>&);
420b57cec5SDimitry Andric  template <class T, class U>
430b57cec5SDimitry Andric    constexpr bool operator>(const optional<T>&, const optional<U>&);
440b57cec5SDimitry Andric  template <class T, class U>
450b57cec5SDimitry Andric    constexpr bool operator<=(const optional<T>&, const optional<U>&);
460b57cec5SDimitry Andric  template <class T, class U>
470b57cec5SDimitry Andric    constexpr bool operator>=(const optional<T>&, const optional<U>&);
48*06c3fb27SDimitry Andric  template<class T, three_way_comparable_with<T> U>
49*06c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
50*06c3fb27SDimitry Andric      operator<=>(const optional<T>&, const optional<U>&); // since C++20
510b57cec5SDimitry Andric
52*06c3fb27SDimitry Andric  // [optional.nullops], comparison with nullopt
530b57cec5SDimitry Andric  template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
54*06c3fb27SDimitry Andric  template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17
55*06c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17
56*06c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17
57*06c3fb27SDimitry Andric  template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;  // until C++17
58*06c3fb27SDimitry Andric  template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;  // until C++17
59*06c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17
60*06c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17
61*06c3fb27SDimitry Andric  template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;  // until C++17
62*06c3fb27SDimitry Andric  template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;  // until C++17
63*06c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17
64*06c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17
65*06c3fb27SDimitry Andric  template<class T>
66*06c3fb27SDimitry Andric    constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept;     // since C++20
670b57cec5SDimitry Andric
68*06c3fb27SDimitry Andric  // [optional.comp.with.t], comparison with T
690b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator==(const optional<T>&, const U&);
700b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator==(const T&, const optional<U>&);
710b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
720b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
730b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<(const optional<T>&, const U&);
740b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<(const T&, const optional<U>&);
750b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
760b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
770b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>(const optional<T>&, const U&);
780b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>(const T&, const optional<U>&);
790b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
800b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
81*06c3fb27SDimitry Andric  template<class T, class U>
82*06c3fb27SDimitry Andric      requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U>
83*06c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
84*06c3fb27SDimitry Andric      operator<=>(const optional<T>&, const U&);                                       // since C++20
850b57cec5SDimitry Andric
86*06c3fb27SDimitry Andric  // [optional.specalg], specialized algorithms
87*06c3fb27SDimitry Andric  template<class T>
88*06c3fb27SDimitry Andric    void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
89*06c3fb27SDimitry Andric
90*06c3fb27SDimitry Andric  template<class T>
91*06c3fb27SDimitry Andric    constexpr optional<see below > make_optional(T&&);
920b57cec5SDimitry Andric  template<class T, class... Args>
930b57cec5SDimitry Andric    constexpr optional<T> make_optional(Args&&... args);
940b57cec5SDimitry Andric  template<class T, class U, class... Args>
950b57cec5SDimitry Andric    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
960b57cec5SDimitry Andric
97*06c3fb27SDimitry Andric  // [optional.hash], hash support
980b57cec5SDimitry Andric  template<class T> struct hash;
990b57cec5SDimitry Andric  template<class T> struct hash<optional<T>>;
1000b57cec5SDimitry Andric
101*06c3fb27SDimitry Andric  template<class T>
102*06c3fb27SDimitry Andric  class optional {
1030b57cec5SDimitry Andric  public:
1040b57cec5SDimitry Andric    using value_type = T;
1050b57cec5SDimitry Andric
106*06c3fb27SDimitry Andric    // [optional.ctor], constructors
1070b57cec5SDimitry Andric    constexpr optional() noexcept;
1080b57cec5SDimitry Andric    constexpr optional(nullopt_t) noexcept;
109bdd1243dSDimitry Andric    constexpr optional(const optional &);
110bdd1243dSDimitry Andric    constexpr optional(optional &&) noexcept(see below);
111*06c3fb27SDimitry Andric    template<class... Args>
112*06c3fb27SDimitry Andric      constexpr explicit optional(in_place_t, Args &&...);
1130b57cec5SDimitry Andric    template<class U, class... Args>
1140b57cec5SDimitry Andric      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
1150b57cec5SDimitry Andric    template<class U = T>
11681ad6265SDimitry Andric      constexpr explicit(see-below) optional(U &&);
1170b57cec5SDimitry Andric    template<class U>
11881ad6265SDimitry Andric      explicit(see-below) optional(const optional<U> &);                          // constexpr in C++20
1190b57cec5SDimitry Andric    template<class U>
12081ad6265SDimitry Andric      explicit(see-below) optional(optional<U> &&);                               // constexpr in C++20
1210b57cec5SDimitry Andric
122*06c3fb27SDimitry Andric    // [optional.dtor], destructor
123fe6060f1SDimitry Andric    ~optional(); // constexpr in C++20
1240b57cec5SDimitry Andric
125*06c3fb27SDimitry Andric    // [optional.assign], assignment
126fe6060f1SDimitry Andric    optional &operator=(nullopt_t) noexcept;                                      // constexpr in C++20
127bdd1243dSDimitry Andric    constexpr optional &operator=(const optional &);
128bdd1243dSDimitry Andric    constexpr optional &operator=(optional &&) noexcept(see below);
129fe6060f1SDimitry Andric    template<class U = T> optional &operator=(U &&);                              // constexpr in C++20
130fe6060f1SDimitry Andric    template<class U> optional &operator=(const optional<U> &);                   // constexpr in C++20
131fe6060f1SDimitry Andric    template<class U> optional &operator=(optional<U> &&);                        // constexpr in C++20
132fe6060f1SDimitry Andric    template<class... Args> T& emplace(Args &&...);                               // constexpr in C++20
133*06c3fb27SDimitry Andric    template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
1340b57cec5SDimitry Andric
135*06c3fb27SDimitry Andric    // [optional.swap], swap
136fe6060f1SDimitry Andric    void swap(optional &) noexcept(see below ); // constexpr in C++20
1370b57cec5SDimitry Andric
138*06c3fb27SDimitry Andric    // [optional.observe], observers
1390b57cec5SDimitry Andric    constexpr T const *operator->() const;
1400b57cec5SDimitry Andric    constexpr T *operator->();
1410b57cec5SDimitry Andric    constexpr T const &operator*() const &;
1420b57cec5SDimitry Andric    constexpr T &operator*() &;
1430b57cec5SDimitry Andric    constexpr T &&operator*() &&;
1440b57cec5SDimitry Andric    constexpr const T &&operator*() const &&;
1450b57cec5SDimitry Andric    constexpr explicit operator bool() const noexcept;
1460b57cec5SDimitry Andric    constexpr bool has_value() const noexcept;
1470b57cec5SDimitry Andric    constexpr T const &value() const &;
1480b57cec5SDimitry Andric    constexpr T &value() &;
1490b57cec5SDimitry Andric    constexpr T &&value() &&;
1500b57cec5SDimitry Andric    constexpr const T &&value() const &&;
1510b57cec5SDimitry Andric    template<class U> constexpr T value_or(U &&) const &;
1520b57cec5SDimitry Andric    template<class U> constexpr T value_or(U &&) &&;
1530b57cec5SDimitry Andric
1540eae32dcSDimitry Andric    // [optional.monadic], monadic operations
1550eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &;         // since C++23
1560eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &&;        // since C++23
1570eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&;    // since C++23
1580eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&&;   // since C++23
1590eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &;        // since C++23
1600eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &&;       // since C++23
1610eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&;   // since C++23
1620eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&&;  // since C++23
1630eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) &&;     // since C++23
1640eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) const&; // since C++23
1650eae32dcSDimitry Andric
166*06c3fb27SDimitry Andric    // [optional.mod], modifiers
167fe6060f1SDimitry Andric    void reset() noexcept;                                      // constexpr in C++20
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric  private:
1700b57cec5SDimitry Andric    T *val;         // exposition only
1710b57cec5SDimitry Andric  };
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric  template<class T>
1740b57cec5SDimitry Andric    optional(T) -> optional<T>;
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric} // namespace std
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric*/
1790b57cec5SDimitry Andric
18081ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
181e8d8bef9SDimitry Andric#include <__availability>
182*06c3fb27SDimitry Andric#include <__compare/compare_three_way_result.h>
183*06c3fb27SDimitry Andric#include <__compare/three_way_comparable.h>
1840eae32dcSDimitry Andric#include <__concepts/invocable.h>
185fe6060f1SDimitry Andric#include <__config>
18681ad6265SDimitry Andric#include <__functional/hash.h>
18781ad6265SDimitry Andric#include <__functional/invoke.h>
188*06c3fb27SDimitry Andric#include <__functional/reference_wrapper.h>
18981ad6265SDimitry Andric#include <__functional/unary_function.h>
190*06c3fb27SDimitry Andric#include <__memory/addressof.h>
19181ad6265SDimitry Andric#include <__memory/construct_at.h>
192*06c3fb27SDimitry Andric#include <__tuple/sfinae_helpers.h>
193*06c3fb27SDimitry Andric#include <__type_traits/add_pointer.h>
194*06c3fb27SDimitry Andric#include <__type_traits/conditional.h>
195*06c3fb27SDimitry Andric#include <__type_traits/conjunction.h>
196*06c3fb27SDimitry Andric#include <__type_traits/decay.h>
197*06c3fb27SDimitry Andric#include <__type_traits/disjunction.h>
198*06c3fb27SDimitry Andric#include <__type_traits/is_array.h>
199*06c3fb27SDimitry Andric#include <__type_traits/is_assignable.h>
200*06c3fb27SDimitry Andric#include <__type_traits/is_constructible.h>
201*06c3fb27SDimitry Andric#include <__type_traits/is_convertible.h>
202*06c3fb27SDimitry Andric#include <__type_traits/is_copy_assignable.h>
203*06c3fb27SDimitry Andric#include <__type_traits/is_copy_constructible.h>
204*06c3fb27SDimitry Andric#include <__type_traits/is_destructible.h>
205*06c3fb27SDimitry Andric#include <__type_traits/is_move_assignable.h>
206*06c3fb27SDimitry Andric#include <__type_traits/is_move_constructible.h>
207*06c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_assignable.h>
208*06c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_constructible.h>
209*06c3fb27SDimitry Andric#include <__type_traits/is_object.h>
210*06c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
211*06c3fb27SDimitry Andric#include <__type_traits/is_scalar.h>
212*06c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
213*06c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_assignable.h>
214*06c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_constructible.h>
215*06c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h>
216*06c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_assignable.h>
217*06c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_constructible.h>
218*06c3fb27SDimitry Andric#include <__type_traits/negation.h>
219*06c3fb27SDimitry Andric#include <__type_traits/remove_const.h>
220*06c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h>
221*06c3fb27SDimitry Andric#include <__type_traits/remove_reference.h>
222*06c3fb27SDimitry Andric#include <__utility/declval.h>
22381ad6265SDimitry Andric#include <__utility/forward.h>
22481ad6265SDimitry Andric#include <__utility/in_place.h>
22581ad6265SDimitry Andric#include <__utility/move.h>
22681ad6265SDimitry Andric#include <__utility/swap.h>
227*06c3fb27SDimitry Andric#include <__verbose_abort>
2280b57cec5SDimitry Andric#include <initializer_list>
2290b57cec5SDimitry Andric#include <new>
2300b57cec5SDimitry Andric#include <stdexcept>
2310b57cec5SDimitry Andric#include <version>
2320b57cec5SDimitry Andric
23381ad6265SDimitry Andric// standard-mandated includes
234bdd1243dSDimitry Andric
235bdd1243dSDimitry Andric// [optional.syn]
23681ad6265SDimitry Andric#include <compare>
23781ad6265SDimitry Andric
2380b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2390b57cec5SDimitry Andric#  pragma GCC system_header
2400b57cec5SDimitry Andric#endif
2410b57cec5SDimitry Andric
242*06c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS
243*06c3fb27SDimitry Andric#include <__undef_macros>
244*06c3fb27SDimitry Andric
2450b57cec5SDimitry Andricnamespace std  // purposefully not using versioning namespace
2460b57cec5SDimitry Andric{
2470b57cec5SDimitry Andric
248*06c3fb27SDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
2490b57cec5SDimitry Andric    : public exception
2500b57cec5SDimitry Andric{
2510b57cec5SDimitry Andricpublic:
2520b57cec5SDimitry Andric    // Get the key function ~bad_optional_access() into the dylib
253bdd1243dSDimitry Andric    ~bad_optional_access() _NOEXCEPT override;
254bdd1243dSDimitry Andric    const char* what() const _NOEXCEPT override;
2550b57cec5SDimitry Andric};
2560b57cec5SDimitry Andric
2570eae32dcSDimitry Andric} // namespace std
2580b57cec5SDimitry Andric
259*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric_LIBCPP_NORETURN
2640b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
2650b57cec5SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
2660b57cec5SDimitry Andricvoid __throw_bad_optional_access() {
267*06c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2680b57cec5SDimitry Andric        throw bad_optional_access();
2690b57cec5SDimitry Andric#else
270*06c3fb27SDimitry Andric    _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode");
2710b57cec5SDimitry Andric#endif
2720b57cec5SDimitry Andric}
2730b57cec5SDimitry Andric
2740b57cec5SDimitry Andricstruct nullopt_t
2750b57cec5SDimitry Andric{
276*06c3fb27SDimitry Andric    struct __secret_tag { explicit __secret_tag() = default; };
2770b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
2780b57cec5SDimitry Andric};
2790b57cec5SDimitry Andric
280349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
2810b57cec5SDimitry Andric
2820eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {};
2830eae32dcSDimitry Andric
2840b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
2850b57cec5SDimitry Andricstruct __optional_destruct_base;
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andrictemplate <class _Tp>
2880b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, false>
2890b57cec5SDimitry Andric{
2900b57cec5SDimitry Andric    typedef _Tp value_type;
2910b57cec5SDimitry Andric    static_assert(is_object_v<value_type>,
2920b57cec5SDimitry Andric        "instantiation of optional with a non-object type is undefined behavior");
2930b57cec5SDimitry Andric    union
2940b57cec5SDimitry Andric    {
2950b57cec5SDimitry Andric        char __null_state_;
2960b57cec5SDimitry Andric        value_type __val_;
2970b57cec5SDimitry Andric    };
2980b57cec5SDimitry Andric    bool __engaged_;
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
301bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base()
3020b57cec5SDimitry Andric    {
3030b57cec5SDimitry Andric        if (__engaged_)
3040b57cec5SDimitry Andric            __val_.~value_type();
3050b57cec5SDimitry Andric    }
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3080b57cec5SDimitry Andric    constexpr __optional_destruct_base() noexcept
3090b57cec5SDimitry Andric        :  __null_state_(),
3100b57cec5SDimitry Andric           __engaged_(false) {}
3110b57cec5SDimitry Andric
3120b57cec5SDimitry Andric    template <class... _Args>
3130b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3140b57cec5SDimitry Andric    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
3150b57cec5SDimitry Andric        :  __val_(_VSTD::forward<_Args>(__args)...),
3160b57cec5SDimitry Andric           __engaged_(true) {}
3170b57cec5SDimitry Andric
318*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23
3190eae32dcSDimitry Andric  template <class _Fp, class... _Args>
3200eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
3210eae32dcSDimitry Andric  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3220eae32dcSDimitry Andric      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
3230eae32dcSDimitry Andric#endif
3240eae32dcSDimitry Andric
3250b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
326bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept
3270b57cec5SDimitry Andric    {
3280b57cec5SDimitry Andric        if (__engaged_)
3290b57cec5SDimitry Andric        {
3300b57cec5SDimitry Andric            __val_.~value_type();
3310b57cec5SDimitry Andric            __engaged_ = false;
3320b57cec5SDimitry Andric        }
3330b57cec5SDimitry Andric    }
3340b57cec5SDimitry Andric};
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andrictemplate <class _Tp>
3370b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, true>
3380b57cec5SDimitry Andric{
3390b57cec5SDimitry Andric    typedef _Tp value_type;
3400b57cec5SDimitry Andric    static_assert(is_object_v<value_type>,
3410b57cec5SDimitry Andric        "instantiation of optional with a non-object type is undefined behavior");
3420b57cec5SDimitry Andric    union
3430b57cec5SDimitry Andric    {
3440b57cec5SDimitry Andric        char __null_state_;
3450b57cec5SDimitry Andric        value_type __val_;
3460b57cec5SDimitry Andric    };
3470b57cec5SDimitry Andric    bool __engaged_;
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3500b57cec5SDimitry Andric    constexpr __optional_destruct_base() noexcept
3510b57cec5SDimitry Andric        :  __null_state_(),
3520b57cec5SDimitry Andric           __engaged_(false) {}
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric    template <class... _Args>
3550b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3560b57cec5SDimitry Andric    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
3570b57cec5SDimitry Andric        :  __val_(_VSTD::forward<_Args>(__args)...),
3580b57cec5SDimitry Andric           __engaged_(true) {}
3590b57cec5SDimitry Andric
360*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23
3610eae32dcSDimitry Andric  template <class _Fp, class... _Args>
3620eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
3630eae32dcSDimitry Andric  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3640eae32dcSDimitry Andric      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
3650eae32dcSDimitry Andric#endif
3660eae32dcSDimitry Andric
3670b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
368bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept
3690b57cec5SDimitry Andric    {
3700b57cec5SDimitry Andric        if (__engaged_)
3710b57cec5SDimitry Andric        {
3720b57cec5SDimitry Andric            __engaged_ = false;
3730b57cec5SDimitry Andric        }
3740b57cec5SDimitry Andric    }
3750b57cec5SDimitry Andric};
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value>
3780b57cec5SDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp>
3790b57cec5SDimitry Andric{
3800b57cec5SDimitry Andric    using __base = __optional_destruct_base<_Tp>;
3810b57cec5SDimitry Andric    using value_type = _Tp;
3820b57cec5SDimitry Andric    using __base::__base;
3830b57cec5SDimitry Andric
3840b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3850b57cec5SDimitry Andric    constexpr bool has_value() const noexcept
3860b57cec5SDimitry Andric    {
3870b57cec5SDimitry Andric        return this->__engaged_;
3880b57cec5SDimitry Andric    }
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3910b57cec5SDimitry Andric    constexpr value_type& __get() & noexcept
3920b57cec5SDimitry Andric    {
3930b57cec5SDimitry Andric        return this->__val_;
3940b57cec5SDimitry Andric    }
3950b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3960b57cec5SDimitry Andric    constexpr const value_type& __get() const& noexcept
3970b57cec5SDimitry Andric    {
3980b57cec5SDimitry Andric        return this->__val_;
3990b57cec5SDimitry Andric    }
4000b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4010b57cec5SDimitry Andric    constexpr value_type&& __get() && noexcept
4020b57cec5SDimitry Andric    {
4030b57cec5SDimitry Andric        return _VSTD::move(this->__val_);
4040b57cec5SDimitry Andric    }
4050b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4060b57cec5SDimitry Andric    constexpr const value_type&& __get() const&& noexcept
4070b57cec5SDimitry Andric    {
4080b57cec5SDimitry Andric        return _VSTD::move(this->__val_);
4090b57cec5SDimitry Andric    }
4100b57cec5SDimitry Andric
4110b57cec5SDimitry Andric    template <class... _Args>
4120b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
413bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args)
4140b57cec5SDimitry Andric    {
415*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
416*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
417fe6060f1SDimitry Andric        _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
418fe6060f1SDimitry Andric#else
4190b57cec5SDimitry Andric        ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
420fe6060f1SDimitry Andric#endif
4210b57cec5SDimitry Andric        this->__engaged_ = true;
4220b57cec5SDimitry Andric    }
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric    template <class _That>
4250b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
426bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt)
4270b57cec5SDimitry Andric    {
4280b57cec5SDimitry Andric        if (__opt.has_value())
4290b57cec5SDimitry Andric            __construct(_VSTD::forward<_That>(__opt).__get());
4300b57cec5SDimitry Andric    }
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric    template <class _That>
4330b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
434bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt)
4350b57cec5SDimitry Andric    {
4360b57cec5SDimitry Andric        if (this->__engaged_ == __opt.has_value())
4370b57cec5SDimitry Andric        {
4380b57cec5SDimitry Andric            if (this->__engaged_)
4390b57cec5SDimitry Andric                this->__val_ = _VSTD::forward<_That>(__opt).__get();
4400b57cec5SDimitry Andric        }
4410b57cec5SDimitry Andric        else
4420b57cec5SDimitry Andric        {
4430b57cec5SDimitry Andric            if (this->__engaged_)
4440b57cec5SDimitry Andric                this->reset();
4450b57cec5SDimitry Andric            else
4460b57cec5SDimitry Andric                __construct(_VSTD::forward<_That>(__opt).__get());
4470b57cec5SDimitry Andric        }
4480b57cec5SDimitry Andric    }
4490b57cec5SDimitry Andric};
4500b57cec5SDimitry Andric
45181ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may
45281ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented
45381ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner.
4540b57cec5SDimitry Andrictemplate <class _Tp>
4550b57cec5SDimitry Andricstruct __optional_storage_base<_Tp, true>
4560b57cec5SDimitry Andric{
4570b57cec5SDimitry Andric    using value_type = _Tp;
4580b57cec5SDimitry Andric    using __raw_type = remove_reference_t<_Tp>;
4590b57cec5SDimitry Andric    __raw_type* __value_;
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric    template <class _Up>
462*06c3fb27SDimitry Andric    static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
463bdd1243dSDimitry Andric        using _RawUp = __libcpp_remove_reference_t<_Up>;
4640b57cec5SDimitry Andric        using _UpPtr = _RawUp*;
465bdd1243dSDimitry Andric        using _RawTp = __libcpp_remove_reference_t<_Tp>;
4660b57cec5SDimitry Andric        using _TpPtr = _RawTp*;
4670b57cec5SDimitry Andric        using _CheckLValueArg = integral_constant<bool,
4680b57cec5SDimitry Andric            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
4690b57cec5SDimitry Andric        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
470bdd1243dSDimitry Andric        ||  is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value
4710b57cec5SDimitry Andric        >;
4720b57cec5SDimitry Andric        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
4730b57cec5SDimitry Andric            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
4740b57cec5SDimitry Andric                is_convertible<_UpPtr, _TpPtr>::value);
4750b57cec5SDimitry Andric    }
4760b57cec5SDimitry Andric
4770b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4780b57cec5SDimitry Andric    constexpr __optional_storage_base() noexcept
4790b57cec5SDimitry Andric        :  __value_(nullptr) {}
4800b57cec5SDimitry Andric
4810b57cec5SDimitry Andric    template <class _UArg>
4820b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4830b57cec5SDimitry Andric    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
4840b57cec5SDimitry Andric        :  __value_(_VSTD::addressof(__uarg))
4850b57cec5SDimitry Andric    {
4860b57cec5SDimitry Andric      static_assert(__can_bind_reference<_UArg>(),
4870b57cec5SDimitry Andric        "Attempted to construct a reference element in tuple from a "
4880b57cec5SDimitry Andric        "possible temporary");
4890b57cec5SDimitry Andric    }
4900b57cec5SDimitry Andric
4910b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
492bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
4930b57cec5SDimitry Andric
4940b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4950b57cec5SDimitry Andric    constexpr bool has_value() const noexcept
4960b57cec5SDimitry Andric      { return __value_ != nullptr; }
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4990b57cec5SDimitry Andric    constexpr value_type& __get() const& noexcept
5000b57cec5SDimitry Andric      { return *__value_; }
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5030b57cec5SDimitry Andric    constexpr value_type&& __get() const&& noexcept
5040b57cec5SDimitry Andric      { return _VSTD::forward<value_type>(*__value_); }
5050b57cec5SDimitry Andric
5060b57cec5SDimitry Andric    template <class _UArg>
5070b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
508bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val)
5090b57cec5SDimitry Andric    {
510*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
5110b57cec5SDimitry Andric        static_assert(__can_bind_reference<_UArg>(),
5120b57cec5SDimitry Andric            "Attempted to construct a reference element in tuple from a "
5130b57cec5SDimitry Andric            "possible temporary");
5140b57cec5SDimitry Andric        __value_ = _VSTD::addressof(__val);
5150b57cec5SDimitry Andric    }
5160b57cec5SDimitry Andric
5170b57cec5SDimitry Andric    template <class _That>
5180b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
519bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt)
5200b57cec5SDimitry Andric    {
5210b57cec5SDimitry Andric        if (__opt.has_value())
5220b57cec5SDimitry Andric            __construct(_VSTD::forward<_That>(__opt).__get());
5230b57cec5SDimitry Andric    }
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andric    template <class _That>
5260b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
527bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt)
5280b57cec5SDimitry Andric    {
5290b57cec5SDimitry Andric        if (has_value() == __opt.has_value())
5300b57cec5SDimitry Andric        {
5310b57cec5SDimitry Andric            if (has_value())
5320b57cec5SDimitry Andric                *__value_ = _VSTD::forward<_That>(__opt).__get();
5330b57cec5SDimitry Andric        }
5340b57cec5SDimitry Andric        else
5350b57cec5SDimitry Andric        {
5360b57cec5SDimitry Andric            if (has_value())
5370b57cec5SDimitry Andric                reset();
5380b57cec5SDimitry Andric            else
5390b57cec5SDimitry Andric                __construct(_VSTD::forward<_That>(__opt).__get());
5400b57cec5SDimitry Andric        }
5410b57cec5SDimitry Andric    }
5420b57cec5SDimitry Andric};
5430b57cec5SDimitry Andric
5440b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
5450b57cec5SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp>
5460b57cec5SDimitry Andric{
5470b57cec5SDimitry Andric    using __optional_storage_base<_Tp>::__optional_storage_base;
5480b57cec5SDimitry Andric};
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andrictemplate <class _Tp>
5510b57cec5SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
5520b57cec5SDimitry Andric{
5530b57cec5SDimitry Andric    using __optional_storage_base<_Tp>::__optional_storage_base;
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5560b57cec5SDimitry Andric    __optional_copy_base() = default;
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
559bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt)
5600b57cec5SDimitry Andric    {
5610b57cec5SDimitry Andric        this->__construct_from(__opt);
5620b57cec5SDimitry Andric    }
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5650b57cec5SDimitry Andric    __optional_copy_base(__optional_copy_base&&) = default;
5660b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5670b57cec5SDimitry Andric    __optional_copy_base& operator=(const __optional_copy_base&) = default;
5680b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5690b57cec5SDimitry Andric    __optional_copy_base& operator=(__optional_copy_base&&) = default;
5700b57cec5SDimitry Andric};
5710b57cec5SDimitry Andric
5720b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
5730b57cec5SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp>
5740b57cec5SDimitry Andric{
5750b57cec5SDimitry Andric    using __optional_copy_base<_Tp>::__optional_copy_base;
5760b57cec5SDimitry Andric};
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andrictemplate <class _Tp>
5790b57cec5SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
5800b57cec5SDimitry Andric{
5810b57cec5SDimitry Andric    using value_type = _Tp;
5820b57cec5SDimitry Andric    using __optional_copy_base<_Tp>::__optional_copy_base;
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5850b57cec5SDimitry Andric    __optional_move_base() = default;
5860b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5870b57cec5SDimitry Andric    __optional_move_base(const __optional_move_base&) = default;
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
590bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_base(__optional_move_base&& __opt)
5910b57cec5SDimitry Andric        noexcept(is_nothrow_move_constructible_v<value_type>)
5920b57cec5SDimitry Andric    {
5930b57cec5SDimitry Andric        this->__construct_from(_VSTD::move(__opt));
5940b57cec5SDimitry Andric    }
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5970b57cec5SDimitry Andric    __optional_move_base& operator=(const __optional_move_base&) = default;
5980b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5990b57cec5SDimitry Andric    __optional_move_base& operator=(__optional_move_base&&) = default;
6000b57cec5SDimitry Andric};
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andrictemplate <class _Tp, bool =
6030b57cec5SDimitry Andric    is_trivially_destructible<_Tp>::value &&
6040b57cec5SDimitry Andric    is_trivially_copy_constructible<_Tp>::value &&
6050b57cec5SDimitry Andric    is_trivially_copy_assignable<_Tp>::value>
6060b57cec5SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp>
6070b57cec5SDimitry Andric{
6080b57cec5SDimitry Andric    using __optional_move_base<_Tp>::__optional_move_base;
6090b57cec5SDimitry Andric};
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andrictemplate <class _Tp>
6120b57cec5SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
6130b57cec5SDimitry Andric{
6140b57cec5SDimitry Andric    using __optional_move_base<_Tp>::__optional_move_base;
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6170b57cec5SDimitry Andric    __optional_copy_assign_base() = default;
6180b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6190b57cec5SDimitry Andric    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
6200b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6210b57cec5SDimitry Andric    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
6220b57cec5SDimitry Andric
6230b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
624bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
6250b57cec5SDimitry Andric    {
6260b57cec5SDimitry Andric        this->__assign_from(__opt);
6270b57cec5SDimitry Andric        return *this;
6280b57cec5SDimitry Andric    }
6290b57cec5SDimitry Andric
6300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6310b57cec5SDimitry Andric    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
6320b57cec5SDimitry Andric};
6330b57cec5SDimitry Andric
6340b57cec5SDimitry Andrictemplate <class _Tp, bool =
6350b57cec5SDimitry Andric    is_trivially_destructible<_Tp>::value &&
6360b57cec5SDimitry Andric    is_trivially_move_constructible<_Tp>::value &&
6370b57cec5SDimitry Andric    is_trivially_move_assignable<_Tp>::value>
6380b57cec5SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
6390b57cec5SDimitry Andric{
6400b57cec5SDimitry Andric    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
6410b57cec5SDimitry Andric};
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andrictemplate <class _Tp>
6440b57cec5SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
6450b57cec5SDimitry Andric{
6460b57cec5SDimitry Andric    using value_type = _Tp;
6470b57cec5SDimitry Andric    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
6480b57cec5SDimitry Andric
6490b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6500b57cec5SDimitry Andric    __optional_move_assign_base() = default;
6510b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6520b57cec5SDimitry Andric    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
6530b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6540b57cec5SDimitry Andric    __optional_move_assign_base(__optional_move_assign_base&&) = default;
6550b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6560b57cec5SDimitry Andric    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
6570b57cec5SDimitry Andric
6580b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
659bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
6600b57cec5SDimitry Andric        noexcept(is_nothrow_move_assignable_v<value_type> &&
6610b57cec5SDimitry Andric                 is_nothrow_move_constructible_v<value_type>)
6620b57cec5SDimitry Andric    {
6630b57cec5SDimitry Andric        this->__assign_from(_VSTD::move(__opt));
6640b57cec5SDimitry Andric        return *this;
6650b57cec5SDimitry Andric    }
6660b57cec5SDimitry Andric};
6670b57cec5SDimitry Andric
6680b57cec5SDimitry Andrictemplate <class _Tp>
6690b57cec5SDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
6700b57cec5SDimitry Andric    is_copy_constructible<_Tp>::value,
6710b57cec5SDimitry Andric    is_move_constructible<_Tp>::value
6720b57cec5SDimitry Andric>;
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andrictemplate <class _Tp>
6750b57cec5SDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base<
6760b57cec5SDimitry Andric    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
6770b57cec5SDimitry Andric    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
6780b57cec5SDimitry Andric>;
6790b57cec5SDimitry Andric
6800b57cec5SDimitry Andrictemplate<class _Tp>
6810eae32dcSDimitry Andricclass optional;
682*06c3fb27SDimitry Andric
683*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
684*06c3fb27SDimitry Andric
685*06c3fb27SDimitry Andrictemplate <class _Tp>
686*06c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); };
687*06c3fb27SDimitry Andric
688*06c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
689*06c3fb27SDimitry Andric
6900eae32dcSDimitry Andrictemplate <class _Tp>
6910eae32dcSDimitry Andricstruct __is_std_optional : false_type {};
6920eae32dcSDimitry Andrictemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
6930eae32dcSDimitry Andric
6940eae32dcSDimitry Andrictemplate <class _Tp>
695*06c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional
6960b57cec5SDimitry Andric    : private __optional_move_assign_base<_Tp>
6970b57cec5SDimitry Andric    , private __optional_sfinae_ctor_base_t<_Tp>
6980b57cec5SDimitry Andric    , private __optional_sfinae_assign_base_t<_Tp>
6990b57cec5SDimitry Andric{
7000b57cec5SDimitry Andric    using __base = __optional_move_assign_base<_Tp>;
7010b57cec5SDimitry Andricpublic:
7020b57cec5SDimitry Andric    using value_type = _Tp;
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andricprivate:
7050b57cec5SDimitry Andric     // Disable the reference extension using this static assert.
706bdd1243dSDimitry Andric    static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,
7070b57cec5SDimitry Andric        "instantiation of optional with in_place_t is ill-formed");
708bdd1243dSDimitry Andric    static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>,
7090b57cec5SDimitry Andric        "instantiation of optional with nullopt_t is ill-formed");
7100b57cec5SDimitry Andric    static_assert(!is_reference_v<value_type>,
7110b57cec5SDimitry Andric        "instantiation of optional with a reference type is ill-formed");
7120b57cec5SDimitry Andric    static_assert(is_destructible_v<value_type>,
7130b57cec5SDimitry Andric        "instantiation of optional with a non-destructible type is ill-formed");
7140b57cec5SDimitry Andric    static_assert(!is_array_v<value_type>,
7150b57cec5SDimitry Andric        "instantiation of optional with an array type is ill-formed");
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from _Up
7180b57cec5SDimitry Andric    struct _CheckOptionalArgsConstructor {
7190b57cec5SDimitry Andric      template <class _Up>
720*06c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
7210b57cec5SDimitry Andric          return is_constructible_v<_Tp, _Up&&> &&
7220b57cec5SDimitry Andric                 is_convertible_v<_Up&&, _Tp>;
7230b57cec5SDimitry Andric      }
7240b57cec5SDimitry Andric
7250b57cec5SDimitry Andric      template <class _Up>
726*06c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
7270b57cec5SDimitry Andric          return is_constructible_v<_Tp, _Up&&> &&
7280b57cec5SDimitry Andric                 !is_convertible_v<_Up&&, _Tp>;
7290b57cec5SDimitry Andric      }
7300b57cec5SDimitry Andric    };
7310b57cec5SDimitry Andric    template <class _Up>
7320b57cec5SDimitry Andric    using _CheckOptionalArgsCtor = _If<
733bdd1243dSDimitry Andric        _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value &&
734bdd1243dSDimitry Andric        _IsNotSame<__remove_cvref_t<_Up>, optional>::value,
7350b57cec5SDimitry Andric        _CheckOptionalArgsConstructor,
7360b57cec5SDimitry Andric        __check_tuple_constructor_fail
7370b57cec5SDimitry Andric    >;
7380b57cec5SDimitry Andric    template <class _QualUp>
7390b57cec5SDimitry Andric    struct _CheckOptionalLikeConstructor {
7400b57cec5SDimitry Andric      template <class _Up, class _Opt = optional<_Up>>
7410b57cec5SDimitry Andric      using __check_constructible_from_opt = _Or<
7420b57cec5SDimitry Andric          is_constructible<_Tp, _Opt&>,
7430b57cec5SDimitry Andric          is_constructible<_Tp, _Opt const&>,
7440b57cec5SDimitry Andric          is_constructible<_Tp, _Opt&&>,
7450b57cec5SDimitry Andric          is_constructible<_Tp, _Opt const&&>,
7460b57cec5SDimitry Andric          is_convertible<_Opt&, _Tp>,
7470b57cec5SDimitry Andric          is_convertible<_Opt const&, _Tp>,
7480b57cec5SDimitry Andric          is_convertible<_Opt&&, _Tp>,
7490b57cec5SDimitry Andric          is_convertible<_Opt const&&, _Tp>
7500b57cec5SDimitry Andric      >;
7510b57cec5SDimitry Andric      template <class _Up, class _Opt = optional<_Up>>
7520b57cec5SDimitry Andric      using __check_assignable_from_opt = _Or<
7530b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt&>,
7540b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt const&>,
7550b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt&&>,
7560b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt const&&>
7570b57cec5SDimitry Andric      >;
7580b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
759*06c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
7600b57cec5SDimitry Andric          return is_convertible<_QUp, _Tp>::value &&
7610b57cec5SDimitry Andric              !__check_constructible_from_opt<_Up>::value;
7620b57cec5SDimitry Andric      }
7630b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
764*06c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
7650b57cec5SDimitry Andric          return !is_convertible<_QUp, _Tp>::value &&
7660b57cec5SDimitry Andric              !__check_constructible_from_opt<_Up>::value;
7670b57cec5SDimitry Andric      }
7680b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
769*06c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
770e8d8bef9SDimitry Andric          // Construction and assignability of _QUp to _Tp has already been
7710b57cec5SDimitry Andric          // checked.
7720b57cec5SDimitry Andric          return !__check_constructible_from_opt<_Up>::value &&
7730b57cec5SDimitry Andric              !__check_assignable_from_opt<_Up>::value;
7740b57cec5SDimitry Andric      }
7750b57cec5SDimitry Andric    };
7760b57cec5SDimitry Andric
7770b57cec5SDimitry Andric    template <class _Up, class _QualUp>
7780b57cec5SDimitry Andric    using _CheckOptionalLikeCtor = _If<
7790b57cec5SDimitry Andric      _And<
7800b57cec5SDimitry Andric         _IsNotSame<_Up, _Tp>,
7810b57cec5SDimitry Andric          is_constructible<_Tp, _QualUp>
7820b57cec5SDimitry Andric      >::value,
7830b57cec5SDimitry Andric      _CheckOptionalLikeConstructor<_QualUp>,
7840b57cec5SDimitry Andric      __check_tuple_constructor_fail
7850b57cec5SDimitry Andric    >;
7860b57cec5SDimitry Andric    template <class _Up, class _QualUp>
7870b57cec5SDimitry Andric    using _CheckOptionalLikeAssign = _If<
7880b57cec5SDimitry Andric      _And<
7890b57cec5SDimitry Andric          _IsNotSame<_Up, _Tp>,
7900b57cec5SDimitry Andric          is_constructible<_Tp, _QualUp>,
7910b57cec5SDimitry Andric          is_assignable<_Tp&, _QualUp>
7920b57cec5SDimitry Andric      >::value,
7930b57cec5SDimitry Andric      _CheckOptionalLikeConstructor<_QualUp>,
7940b57cec5SDimitry Andric      __check_tuple_constructor_fail
7950b57cec5SDimitry Andric    >;
7960eae32dcSDimitry Andric
7970b57cec5SDimitry Andricpublic:
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
8000b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
8010b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
8020b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
8030b57cec5SDimitry Andric
804349cc55cSDimitry Andric    template <class _InPlaceT, class... _Args, class = enable_if_t<
8050b57cec5SDimitry Andric          _And<
8060b57cec5SDimitry Andric              _IsSame<_InPlaceT, in_place_t>,
8070b57cec5SDimitry Andric              is_constructible<value_type, _Args...>
8080b57cec5SDimitry Andric            >::value
8090b57cec5SDimitry Andric        >
8100b57cec5SDimitry Andric    >
8110b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
8120b57cec5SDimitry Andric    constexpr explicit optional(_InPlaceT, _Args&&... __args)
8130b57cec5SDimitry Andric        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
8140b57cec5SDimitry Andric
815349cc55cSDimitry Andric    template <class _Up, class... _Args, class = enable_if_t<
8160b57cec5SDimitry Andric        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
8170b57cec5SDimitry Andric    >
8180b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
8190b57cec5SDimitry Andric    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
8200b57cec5SDimitry Andric        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
8210b57cec5SDimitry Andric
822349cc55cSDimitry Andric    template <class _Up = value_type, enable_if_t<
8230b57cec5SDimitry Andric        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
8240b57cec5SDimitry Andric    , int> = 0>
8250b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
8260b57cec5SDimitry Andric    constexpr optional(_Up&& __v)
8270b57cec5SDimitry Andric        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
8280b57cec5SDimitry Andric
829349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8300b57cec5SDimitry Andric        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
8310b57cec5SDimitry Andric    , int> = 0>
8320b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
8330b57cec5SDimitry Andric    constexpr explicit optional(_Up&& __v)
8340b57cec5SDimitry Andric        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
8350b57cec5SDimitry Andric
8360b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from const optional<_Up>&
837349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8380b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
8390b57cec5SDimitry Andric    , int> = 0>
8400b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
841bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v)
8420b57cec5SDimitry Andric    {
8430b57cec5SDimitry Andric        this->__construct_from(__v);
8440b57cec5SDimitry Andric    }
845349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8460b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
8470b57cec5SDimitry Andric    , int> = 0>
8480b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
849bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v)
8500b57cec5SDimitry Andric    {
8510b57cec5SDimitry Andric        this->__construct_from(__v);
8520b57cec5SDimitry Andric    }
8530b57cec5SDimitry Andric
8540b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from optional<_Up>&&
855349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8560b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
8570b57cec5SDimitry Andric    , int> = 0>
8580b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
859bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v)
8600b57cec5SDimitry Andric    {
8610b57cec5SDimitry Andric        this->__construct_from(_VSTD::move(__v));
8620b57cec5SDimitry Andric    }
863349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8640b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
8650b57cec5SDimitry Andric    , int> = 0>
8660b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
867bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v)
8680b57cec5SDimitry Andric    {
8690b57cec5SDimitry Andric        this->__construct_from(_VSTD::move(__v));
8700b57cec5SDimitry Andric    }
8710b57cec5SDimitry Andric
872*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23
8730eae32dcSDimitry Andric  template<class _Fp, class... _Args>
8740eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
8750eae32dcSDimitry Andric  constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
8760eae32dcSDimitry Andric      : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
8770eae32dcSDimitry Andric  }
8780eae32dcSDimitry Andric#endif
8790eae32dcSDimitry Andric
8800b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
881bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept
8820b57cec5SDimitry Andric    {
8830b57cec5SDimitry Andric        reset();
8840b57cec5SDimitry Andric        return *this;
8850b57cec5SDimitry Andric    }
8860b57cec5SDimitry Andric
887*06c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
888*06c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default;
8890b57cec5SDimitry Andric
8900b57cec5SDimitry Andric    // LWG2756
8910b57cec5SDimitry Andric    template <class _Up = value_type,
892349cc55cSDimitry Andric              class = enable_if_t<
8930b57cec5SDimitry Andric                      _And<
894bdd1243dSDimitry Andric                          _IsNotSame<__remove_cvref_t<_Up>, optional>,
8950b57cec5SDimitry Andric                          _Or<
896bdd1243dSDimitry Andric                              _IsNotSame<__remove_cvref_t<_Up>, value_type>,
8970b57cec5SDimitry Andric                              _Not<is_scalar<value_type>>
8980b57cec5SDimitry Andric                          >,
8990b57cec5SDimitry Andric                          is_constructible<value_type, _Up>,
9000b57cec5SDimitry Andric                          is_assignable<value_type&, _Up>
9010b57cec5SDimitry Andric                      >::value>
9020b57cec5SDimitry Andric             >
9030b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
904bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
9050b57cec5SDimitry Andric    operator=(_Up&& __v)
9060b57cec5SDimitry Andric    {
9070b57cec5SDimitry Andric        if (this->has_value())
9080b57cec5SDimitry Andric            this->__get() = _VSTD::forward<_Up>(__v);
9090b57cec5SDimitry Andric        else
9100b57cec5SDimitry Andric            this->__construct(_VSTD::forward<_Up>(__v));
9110b57cec5SDimitry Andric        return *this;
9120b57cec5SDimitry Andric    }
9130b57cec5SDimitry Andric
9140b57cec5SDimitry Andric    // LWG2756
915349cc55cSDimitry Andric    template <class _Up, enable_if_t<
9160b57cec5SDimitry Andric        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
9170b57cec5SDimitry Andric    , int> = 0>
9180b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
919bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
9200b57cec5SDimitry Andric    operator=(const optional<_Up>& __v)
9210b57cec5SDimitry Andric    {
9220b57cec5SDimitry Andric        this->__assign_from(__v);
9230b57cec5SDimitry Andric        return *this;
9240b57cec5SDimitry Andric    }
9250b57cec5SDimitry Andric
9260b57cec5SDimitry Andric    // LWG2756
927349cc55cSDimitry Andric    template <class _Up, enable_if_t<
9280b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
9290b57cec5SDimitry Andric    , int> = 0>
9300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
931bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
9320b57cec5SDimitry Andric    operator=(optional<_Up>&& __v)
9330b57cec5SDimitry Andric    {
9340b57cec5SDimitry Andric        this->__assign_from(_VSTD::move(__v));
9350b57cec5SDimitry Andric        return *this;
9360b57cec5SDimitry Andric    }
9370b57cec5SDimitry Andric
9380b57cec5SDimitry Andric    template <class... _Args,
939349cc55cSDimitry Andric              class = enable_if_t
9400b57cec5SDimitry Andric                      <
9410b57cec5SDimitry Andric                          is_constructible_v<value_type, _Args...>
9420b57cec5SDimitry Andric                      >
9430b57cec5SDimitry Andric             >
9440b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
945bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp &
9460b57cec5SDimitry Andric    emplace(_Args&&... __args)
9470b57cec5SDimitry Andric    {
9480b57cec5SDimitry Andric        reset();
9490b57cec5SDimitry Andric        this->__construct(_VSTD::forward<_Args>(__args)...);
9500b57cec5SDimitry Andric        return this->__get();
9510b57cec5SDimitry Andric    }
9520b57cec5SDimitry Andric
9530b57cec5SDimitry Andric    template <class _Up, class... _Args,
954349cc55cSDimitry Andric              class = enable_if_t
9550b57cec5SDimitry Andric                      <
9560b57cec5SDimitry Andric                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
9570b57cec5SDimitry Andric                      >
9580b57cec5SDimitry Andric             >
9590b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
960bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp &
9610b57cec5SDimitry Andric    emplace(initializer_list<_Up> __il, _Args&&... __args)
9620b57cec5SDimitry Andric    {
9630b57cec5SDimitry Andric        reset();
9640b57cec5SDimitry Andric        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
9650b57cec5SDimitry Andric        return this->__get();
9660b57cec5SDimitry Andric    }
9670b57cec5SDimitry Andric
9680b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
969bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional& __opt)
9700b57cec5SDimitry Andric        noexcept(is_nothrow_move_constructible_v<value_type> &&
9710b57cec5SDimitry Andric                 is_nothrow_swappable_v<value_type>)
9720b57cec5SDimitry Andric    {
9730b57cec5SDimitry Andric        if (this->has_value() == __opt.has_value())
9740b57cec5SDimitry Andric        {
9750b57cec5SDimitry Andric            using _VSTD::swap;
9760b57cec5SDimitry Andric            if (this->has_value())
9770b57cec5SDimitry Andric                swap(this->__get(), __opt.__get());
9780b57cec5SDimitry Andric        }
9790b57cec5SDimitry Andric        else
9800b57cec5SDimitry Andric        {
9810b57cec5SDimitry Andric            if (this->has_value())
9820b57cec5SDimitry Andric            {
9830b57cec5SDimitry Andric                __opt.__construct(_VSTD::move(this->__get()));
9840b57cec5SDimitry Andric                reset();
9850b57cec5SDimitry Andric            }
9860b57cec5SDimitry Andric            else
9870b57cec5SDimitry Andric            {
9880b57cec5SDimitry Andric                this->__construct(_VSTD::move(__opt.__get()));
9890b57cec5SDimitry Andric                __opt.reset();
9900b57cec5SDimitry Andric            }
9910b57cec5SDimitry Andric        }
9920b57cec5SDimitry Andric    }
9930b57cec5SDimitry Andric
9940b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9950b57cec5SDimitry Andric    constexpr
9960b57cec5SDimitry Andric    add_pointer_t<value_type const>
9970b57cec5SDimitry Andric    operator->() const
9980b57cec5SDimitry Andric    {
999*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
10000b57cec5SDimitry Andric        return _VSTD::addressof(this->__get());
10010b57cec5SDimitry Andric    }
10020b57cec5SDimitry Andric
10030b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10040b57cec5SDimitry Andric    constexpr
10050b57cec5SDimitry Andric    add_pointer_t<value_type>
10060b57cec5SDimitry Andric    operator->()
10070b57cec5SDimitry Andric    {
1008*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
10090b57cec5SDimitry Andric        return _VSTD::addressof(this->__get());
10100b57cec5SDimitry Andric    }
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10130b57cec5SDimitry Andric    constexpr
10140b57cec5SDimitry Andric    const value_type&
1015fe6060f1SDimitry Andric    operator*() const& noexcept
10160b57cec5SDimitry Andric    {
1017*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
10180b57cec5SDimitry Andric        return this->__get();
10190b57cec5SDimitry Andric    }
10200b57cec5SDimitry Andric
10210b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10220b57cec5SDimitry Andric    constexpr
10230b57cec5SDimitry Andric    value_type&
1024fe6060f1SDimitry Andric    operator*() & noexcept
10250b57cec5SDimitry Andric    {
1026*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
10270b57cec5SDimitry Andric        return this->__get();
10280b57cec5SDimitry Andric    }
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10310b57cec5SDimitry Andric    constexpr
10320b57cec5SDimitry Andric    value_type&&
1033fe6060f1SDimitry Andric    operator*() && noexcept
10340b57cec5SDimitry Andric    {
1035*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
10360b57cec5SDimitry Andric        return _VSTD::move(this->__get());
10370b57cec5SDimitry Andric    }
10380b57cec5SDimitry Andric
10390b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10400b57cec5SDimitry Andric    constexpr
10410b57cec5SDimitry Andric    const value_type&&
1042fe6060f1SDimitry Andric    operator*() const&& noexcept
10430b57cec5SDimitry Andric    {
1044*06c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
10450b57cec5SDimitry Andric        return _VSTD::move(this->__get());
10460b57cec5SDimitry Andric    }
10470b57cec5SDimitry Andric
10480b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10490b57cec5SDimitry Andric    constexpr explicit operator bool() const noexcept { return has_value(); }
10500b57cec5SDimitry Andric
10510b57cec5SDimitry Andric    using __base::has_value;
10520b57cec5SDimitry Andric    using __base::__get;
10530b57cec5SDimitry Andric
10540b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10550b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10560b57cec5SDimitry Andric    constexpr value_type const& value() const&
10570b57cec5SDimitry Andric    {
10580b57cec5SDimitry Andric        if (!this->has_value())
10590b57cec5SDimitry Andric            __throw_bad_optional_access();
10600b57cec5SDimitry Andric        return this->__get();
10610b57cec5SDimitry Andric    }
10620b57cec5SDimitry Andric
10630b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10640b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10650b57cec5SDimitry Andric    constexpr value_type& value() &
10660b57cec5SDimitry Andric    {
10670b57cec5SDimitry Andric        if (!this->has_value())
10680b57cec5SDimitry Andric            __throw_bad_optional_access();
10690b57cec5SDimitry Andric        return this->__get();
10700b57cec5SDimitry Andric    }
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10730b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10740b57cec5SDimitry Andric    constexpr value_type&& value() &&
10750b57cec5SDimitry Andric    {
10760b57cec5SDimitry Andric        if (!this->has_value())
10770b57cec5SDimitry Andric            __throw_bad_optional_access();
10780b57cec5SDimitry Andric        return _VSTD::move(this->__get());
10790b57cec5SDimitry Andric    }
10800b57cec5SDimitry Andric
10810b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10820b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10830b57cec5SDimitry Andric    constexpr value_type const&& value() const&&
10840b57cec5SDimitry Andric    {
10850b57cec5SDimitry Andric        if (!this->has_value())
10860b57cec5SDimitry Andric            __throw_bad_optional_access();
10870b57cec5SDimitry Andric        return _VSTD::move(this->__get());
10880b57cec5SDimitry Andric    }
10890b57cec5SDimitry Andric
10900b57cec5SDimitry Andric    template <class _Up>
10910b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10920b57cec5SDimitry Andric    constexpr value_type value_or(_Up&& __v) const&
10930b57cec5SDimitry Andric    {
10940b57cec5SDimitry Andric        static_assert(is_copy_constructible_v<value_type>,
10950b57cec5SDimitry Andric                      "optional<T>::value_or: T must be copy constructible");
10960b57cec5SDimitry Andric        static_assert(is_convertible_v<_Up, value_type>,
10970b57cec5SDimitry Andric                      "optional<T>::value_or: U must be convertible to T");
10980b57cec5SDimitry Andric        return this->has_value() ? this->__get() :
10990b57cec5SDimitry Andric                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
11000b57cec5SDimitry Andric    }
11010b57cec5SDimitry Andric
11020b57cec5SDimitry Andric    template <class _Up>
11030b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
11040b57cec5SDimitry Andric    constexpr value_type value_or(_Up&& __v) &&
11050b57cec5SDimitry Andric    {
11060b57cec5SDimitry Andric        static_assert(is_move_constructible_v<value_type>,
11070b57cec5SDimitry Andric                      "optional<T>::value_or: T must be move constructible");
11080b57cec5SDimitry Andric        static_assert(is_convertible_v<_Up, value_type>,
11090b57cec5SDimitry Andric                      "optional<T>::value_or: U must be convertible to T");
11100b57cec5SDimitry Andric        return this->has_value() ? _VSTD::move(this->__get()) :
11110b57cec5SDimitry Andric                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
11120b57cec5SDimitry Andric    }
11130b57cec5SDimitry Andric
1114*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23
11150eae32dcSDimitry Andric  template<class _Func>
111681ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11170eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) & {
11180eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&>;
11190eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
11200eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
11210eae32dcSDimitry Andric    if (*this)
11220eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
11230eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
11240eae32dcSDimitry Andric  }
11250eae32dcSDimitry Andric
11260eae32dcSDimitry Andric  template<class _Func>
112781ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11280eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) const& {
11290eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&>;
11300eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
11310eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
11320eae32dcSDimitry Andric    if (*this)
11330eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
11340eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
11350eae32dcSDimitry Andric  }
11360eae32dcSDimitry Andric
11370eae32dcSDimitry Andric  template<class _Func>
113881ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11390eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) && {
11400eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&&>;
11410eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
11420eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
11430eae32dcSDimitry Andric    if (*this)
11440eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
11450eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
11460eae32dcSDimitry Andric  }
11470eae32dcSDimitry Andric
11480eae32dcSDimitry Andric  template<class _Func>
11490eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
11500eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) const&& {
11510eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&&>;
11520eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
11530eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
11540eae32dcSDimitry Andric    if (*this)
11550eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
11560eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
11570eae32dcSDimitry Andric  }
11580eae32dcSDimitry Andric
11590eae32dcSDimitry Andric  template<class _Func>
116081ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11610eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) & {
11620eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
11630eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
11640eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11650eae32dcSDimitry Andric                  "Result of f(value()) should not be std::in_place_t");
11660eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11670eae32dcSDimitry Andric                  "Result of f(value()) should not be std::nullopt_t");
11680eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
11690eae32dcSDimitry Andric    if (*this)
11700eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
11710eae32dcSDimitry Andric    return optional<_Up>();
11720eae32dcSDimitry Andric  }
11730eae32dcSDimitry Andric
11740eae32dcSDimitry Andric  template<class _Func>
117581ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11760eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) const& {
11770eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
11780eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
11790eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11800eae32dcSDimitry Andric                  "Result of f(value()) should not be std::in_place_t");
11810eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11820eae32dcSDimitry Andric                  "Result of f(value()) should not be std::nullopt_t");
11830eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
11840eae32dcSDimitry Andric    if (*this)
11850eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
11860eae32dcSDimitry Andric    return optional<_Up>();
11870eae32dcSDimitry Andric  }
11880eae32dcSDimitry Andric
11890eae32dcSDimitry Andric  template<class _Func>
119081ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11910eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) && {
11920eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
11930eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
11940eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11950eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::in_place_t");
11960eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11970eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::nullopt_t");
11980eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
11990eae32dcSDimitry Andric    if (*this)
12000eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
12010eae32dcSDimitry Andric    return optional<_Up>();
12020eae32dcSDimitry Andric  }
12030eae32dcSDimitry Andric
12040eae32dcSDimitry Andric  template<class _Func>
120581ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
12060eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) const&& {
12070eae32dcSDimitry Andric    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
12080eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
12090eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
12100eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::in_place_t");
12110eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
12120eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::nullopt_t");
12130eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
12140eae32dcSDimitry Andric    if (*this)
12150eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
12160eae32dcSDimitry Andric    return optional<_Up>();
12170eae32dcSDimitry Andric  }
12180eae32dcSDimitry Andric
12190eae32dcSDimitry Andric  template<invocable _Func>
12200eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
12210eae32dcSDimitry Andric  constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
12220eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
12230eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
12240eae32dcSDimitry Andric    if (*this)
12250eae32dcSDimitry Andric      return *this;
12260eae32dcSDimitry Andric    return _VSTD::forward<_Func>(__f)();
12270eae32dcSDimitry Andric  }
12280eae32dcSDimitry Andric
12290eae32dcSDimitry Andric  template<invocable _Func>
12300eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
12310eae32dcSDimitry Andric  constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
12320eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
12330eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
12340eae32dcSDimitry Andric    if (*this)
12350eae32dcSDimitry Andric      return _VSTD::move(*this);
12360eae32dcSDimitry Andric    return _VSTD::forward<_Func>(__f)();
12370eae32dcSDimitry Andric  }
1238*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 23
12390eae32dcSDimitry Andric
12400b57cec5SDimitry Andric    using __base::reset;
12410b57cec5SDimitry Andric};
12420b57cec5SDimitry Andric
1243349cc55cSDimitry Andric#if _LIBCPP_STD_VER >= 17
124404eeddc0SDimitry Andrictemplate<class _Tp>
124504eeddc0SDimitry Andric    optional(_Tp) -> optional<_Tp>;
12460b57cec5SDimitry Andric#endif
12470b57cec5SDimitry Andric
12480b57cec5SDimitry Andric// Comparisons between optionals
12490b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12500b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1251349cc55cSDimitry Andricenable_if_t<
1252bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() ==
1253bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
12540b57cec5SDimitry Andric    bool
12550b57cec5SDimitry Andric>
12560b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y)
12570b57cec5SDimitry Andric{
12580b57cec5SDimitry Andric    if (static_cast<bool>(__x) != static_cast<bool>(__y))
12590b57cec5SDimitry Andric        return false;
12600b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
12610b57cec5SDimitry Andric        return true;
12620b57cec5SDimitry Andric    return *__x == *__y;
12630b57cec5SDimitry Andric}
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12660b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1267349cc55cSDimitry Andricenable_if_t<
1268bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() !=
1269bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
12700b57cec5SDimitry Andric    bool
12710b57cec5SDimitry Andric>
12720b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
12730b57cec5SDimitry Andric{
12740b57cec5SDimitry Andric    if (static_cast<bool>(__x) != static_cast<bool>(__y))
12750b57cec5SDimitry Andric        return true;
12760b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
12770b57cec5SDimitry Andric        return false;
12780b57cec5SDimitry Andric    return *__x != *__y;
12790b57cec5SDimitry Andric}
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12820b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1283349cc55cSDimitry Andricenable_if_t<
1284bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <
1285bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
12860b57cec5SDimitry Andric    bool
12870b57cec5SDimitry Andric>
12880b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y)
12890b57cec5SDimitry Andric{
12900b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
12910b57cec5SDimitry Andric        return false;
12920b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
12930b57cec5SDimitry Andric        return true;
12940b57cec5SDimitry Andric    return *__x < *__y;
12950b57cec5SDimitry Andric}
12960b57cec5SDimitry Andric
12970b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12980b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1299349cc55cSDimitry Andricenable_if_t<
1300bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >
1301bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
13020b57cec5SDimitry Andric    bool
13030b57cec5SDimitry Andric>
13040b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y)
13050b57cec5SDimitry Andric{
13060b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
13070b57cec5SDimitry Andric        return false;
13080b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
13090b57cec5SDimitry Andric        return true;
13100b57cec5SDimitry Andric    return *__x > *__y;
13110b57cec5SDimitry Andric}
13120b57cec5SDimitry Andric
13130b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
13140b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1315349cc55cSDimitry Andricenable_if_t<
1316bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <=
1317bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
13180b57cec5SDimitry Andric    bool
13190b57cec5SDimitry Andric>
13200b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
13210b57cec5SDimitry Andric{
13220b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
13230b57cec5SDimitry Andric        return true;
13240b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
13250b57cec5SDimitry Andric        return false;
13260b57cec5SDimitry Andric    return *__x <= *__y;
13270b57cec5SDimitry Andric}
13280b57cec5SDimitry Andric
13290b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
13300b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1331349cc55cSDimitry Andricenable_if_t<
1332bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >=
1333bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
13340b57cec5SDimitry Andric    bool
13350b57cec5SDimitry Andric>
13360b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
13370b57cec5SDimitry Andric{
13380b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
13390b57cec5SDimitry Andric        return true;
13400b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
13410b57cec5SDimitry Andric        return false;
13420b57cec5SDimitry Andric    return *__x >= *__y;
13430b57cec5SDimitry Andric}
13440b57cec5SDimitry Andric
1345*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
1346*06c3fb27SDimitry Andric
1347*06c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up>
1348*06c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
1349*06c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) {
1350*06c3fb27SDimitry Andric    if (__x && __y)
1351*06c3fb27SDimitry Andric        return *__x <=> *__y;
1352*06c3fb27SDimitry Andric    return __x.has_value() <=> __y.has_value();
1353*06c3fb27SDimitry Andric}
1354*06c3fb27SDimitry Andric
1355*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 20
1356*06c3fb27SDimitry Andric
13570b57cec5SDimitry Andric// Comparisons with nullopt
13580b57cec5SDimitry Andrictemplate <class _Tp>
13590b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13600b57cec5SDimitry Andricbool
13610b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, nullopt_t) noexcept
13620b57cec5SDimitry Andric{
13630b57cec5SDimitry Andric    return !static_cast<bool>(__x);
13640b57cec5SDimitry Andric}
13650b57cec5SDimitry Andric
1366*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER <= 17
1367*06c3fb27SDimitry Andric
13680b57cec5SDimitry Andrictemplate <class _Tp>
13690b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13700b57cec5SDimitry Andricbool
13710b57cec5SDimitry Andricoperator==(nullopt_t, const optional<_Tp>& __x) noexcept
13720b57cec5SDimitry Andric{
13730b57cec5SDimitry Andric    return !static_cast<bool>(__x);
13740b57cec5SDimitry Andric}
13750b57cec5SDimitry Andric
13760b57cec5SDimitry Andrictemplate <class _Tp>
13770b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13780b57cec5SDimitry Andricbool
13790b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept
13800b57cec5SDimitry Andric{
13810b57cec5SDimitry Andric    return static_cast<bool>(__x);
13820b57cec5SDimitry Andric}
13830b57cec5SDimitry Andric
13840b57cec5SDimitry Andrictemplate <class _Tp>
13850b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13860b57cec5SDimitry Andricbool
13870b57cec5SDimitry Andricoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept
13880b57cec5SDimitry Andric{
13890b57cec5SDimitry Andric    return static_cast<bool>(__x);
13900b57cec5SDimitry Andric}
13910b57cec5SDimitry Andric
13920b57cec5SDimitry Andrictemplate <class _Tp>
13930b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13940b57cec5SDimitry Andricbool
13950b57cec5SDimitry Andricoperator<(const optional<_Tp>&, nullopt_t) noexcept
13960b57cec5SDimitry Andric{
13970b57cec5SDimitry Andric    return false;
13980b57cec5SDimitry Andric}
13990b57cec5SDimitry Andric
14000b57cec5SDimitry Andrictemplate <class _Tp>
14010b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14020b57cec5SDimitry Andricbool
14030b57cec5SDimitry Andricoperator<(nullopt_t, const optional<_Tp>& __x) noexcept
14040b57cec5SDimitry Andric{
14050b57cec5SDimitry Andric    return static_cast<bool>(__x);
14060b57cec5SDimitry Andric}
14070b57cec5SDimitry Andric
14080b57cec5SDimitry Andrictemplate <class _Tp>
14090b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14100b57cec5SDimitry Andricbool
14110b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept
14120b57cec5SDimitry Andric{
14130b57cec5SDimitry Andric    return !static_cast<bool>(__x);
14140b57cec5SDimitry Andric}
14150b57cec5SDimitry Andric
14160b57cec5SDimitry Andrictemplate <class _Tp>
14170b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14180b57cec5SDimitry Andricbool
14190b57cec5SDimitry Andricoperator<=(nullopt_t, const optional<_Tp>&) noexcept
14200b57cec5SDimitry Andric{
14210b57cec5SDimitry Andric    return true;
14220b57cec5SDimitry Andric}
14230b57cec5SDimitry Andric
14240b57cec5SDimitry Andrictemplate <class _Tp>
14250b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14260b57cec5SDimitry Andricbool
14270b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, nullopt_t) noexcept
14280b57cec5SDimitry Andric{
14290b57cec5SDimitry Andric    return static_cast<bool>(__x);
14300b57cec5SDimitry Andric}
14310b57cec5SDimitry Andric
14320b57cec5SDimitry Andrictemplate <class _Tp>
14330b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14340b57cec5SDimitry Andricbool
14350b57cec5SDimitry Andricoperator>(nullopt_t, const optional<_Tp>&) noexcept
14360b57cec5SDimitry Andric{
14370b57cec5SDimitry Andric    return false;
14380b57cec5SDimitry Andric}
14390b57cec5SDimitry Andric
14400b57cec5SDimitry Andrictemplate <class _Tp>
14410b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14420b57cec5SDimitry Andricbool
14430b57cec5SDimitry Andricoperator>=(const optional<_Tp>&, nullopt_t) noexcept
14440b57cec5SDimitry Andric{
14450b57cec5SDimitry Andric    return true;
14460b57cec5SDimitry Andric}
14470b57cec5SDimitry Andric
14480b57cec5SDimitry Andrictemplate <class _Tp>
14490b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
14500b57cec5SDimitry Andricbool
14510b57cec5SDimitry Andricoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept
14520b57cec5SDimitry Andric{
14530b57cec5SDimitry Andric    return !static_cast<bool>(__x);
14540b57cec5SDimitry Andric}
14550b57cec5SDimitry Andric
1456*06c3fb27SDimitry Andric#else // _LIBCPP_STD_VER <= 17
1457*06c3fb27SDimitry Andric
1458*06c3fb27SDimitry Andrictemplate <class _Tp>
1459*06c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept {
1460*06c3fb27SDimitry Andric    return __x.has_value() <=> false;
1461*06c3fb27SDimitry Andric}
1462*06c3fb27SDimitry Andric
1463*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER <= 17
1464*06c3fb27SDimitry Andric
14650b57cec5SDimitry Andric// Comparisons with T
14660b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14670b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1468349cc55cSDimitry Andricenable_if_t<
1469bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() ==
1470bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14710b57cec5SDimitry Andric    bool
14720b57cec5SDimitry Andric>
14730b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v)
14740b57cec5SDimitry Andric{
14750b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x == __v : false;
14760b57cec5SDimitry Andric}
14770b57cec5SDimitry Andric
14780b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14790b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1480349cc55cSDimitry Andricenable_if_t<
1481bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() ==
1482bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14830b57cec5SDimitry Andric    bool
14840b57cec5SDimitry Andric>
14850b57cec5SDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x)
14860b57cec5SDimitry Andric{
14870b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v == *__x : false;
14880b57cec5SDimitry Andric}
14890b57cec5SDimitry Andric
14900b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14910b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1492349cc55cSDimitry Andricenable_if_t<
1493bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() !=
1494bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14950b57cec5SDimitry Andric    bool
14960b57cec5SDimitry Andric>
14970b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v)
14980b57cec5SDimitry Andric{
14990b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x != __v : true;
15000b57cec5SDimitry Andric}
15010b57cec5SDimitry Andric
15020b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15030b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1504349cc55cSDimitry Andricenable_if_t<
1505bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() !=
1506bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15070b57cec5SDimitry Andric    bool
15080b57cec5SDimitry Andric>
15090b57cec5SDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x)
15100b57cec5SDimitry Andric{
15110b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v != *__x : true;
15120b57cec5SDimitry Andric}
15130b57cec5SDimitry Andric
15140b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15150b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1516349cc55cSDimitry Andricenable_if_t<
1517bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <
1518bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15190b57cec5SDimitry Andric    bool
15200b57cec5SDimitry Andric>
15210b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v)
15220b57cec5SDimitry Andric{
15230b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x < __v : true;
15240b57cec5SDimitry Andric}
15250b57cec5SDimitry Andric
15260b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15270b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1528349cc55cSDimitry Andricenable_if_t<
1529bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <
1530bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15310b57cec5SDimitry Andric    bool
15320b57cec5SDimitry Andric>
15330b57cec5SDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x)
15340b57cec5SDimitry Andric{
15350b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v < *__x : false;
15360b57cec5SDimitry Andric}
15370b57cec5SDimitry Andric
15380b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15390b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1540349cc55cSDimitry Andricenable_if_t<
1541bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <=
1542bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15430b57cec5SDimitry Andric    bool
15440b57cec5SDimitry Andric>
15450b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v)
15460b57cec5SDimitry Andric{
15470b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x <= __v : true;
15480b57cec5SDimitry Andric}
15490b57cec5SDimitry Andric
15500b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15510b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1552349cc55cSDimitry Andricenable_if_t<
1553bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <=
1554bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15550b57cec5SDimitry Andric    bool
15560b57cec5SDimitry Andric>
15570b57cec5SDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x)
15580b57cec5SDimitry Andric{
15590b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v <= *__x : false;
15600b57cec5SDimitry Andric}
15610b57cec5SDimitry Andric
15620b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15630b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1564349cc55cSDimitry Andricenable_if_t<
1565bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >
1566bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15670b57cec5SDimitry Andric    bool
15680b57cec5SDimitry Andric>
15690b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v)
15700b57cec5SDimitry Andric{
15710b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x > __v : false;
15720b57cec5SDimitry Andric}
15730b57cec5SDimitry Andric
15740b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15750b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1576349cc55cSDimitry Andricenable_if_t<
1577bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >
1578bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15790b57cec5SDimitry Andric    bool
15800b57cec5SDimitry Andric>
15810b57cec5SDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x)
15820b57cec5SDimitry Andric{
15830b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v > *__x : true;
15840b57cec5SDimitry Andric}
15850b57cec5SDimitry Andric
15860b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15870b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1588349cc55cSDimitry Andricenable_if_t<
1589bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >=
1590bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15910b57cec5SDimitry Andric    bool
15920b57cec5SDimitry Andric>
15930b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v)
15940b57cec5SDimitry Andric{
15950b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x >= __v : false;
15960b57cec5SDimitry Andric}
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15990b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1600349cc55cSDimitry Andricenable_if_t<
1601bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >=
1602bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
16030b57cec5SDimitry Andric    bool
16040b57cec5SDimitry Andric>
16050b57cec5SDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x)
16060b57cec5SDimitry Andric{
16070b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v >= *__x : true;
16080b57cec5SDimitry Andric}
16090b57cec5SDimitry Andric
1610*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
1611*06c3fb27SDimitry Andric
1612*06c3fb27SDimitry Andrictemplate <class _Tp, class _Up>
1613*06c3fb27SDimitry Andric  requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up>
1614*06c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
1615*06c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) {
1616*06c3fb27SDimitry Andric    return __x.has_value() ? *__x <=> __v : strong_ordering::less;
1617*06c3fb27SDimitry Andric}
1618*06c3fb27SDimitry Andric
1619*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 20
1620*06c3fb27SDimitry Andric
16210b57cec5SDimitry Andric
16220b57cec5SDimitry Andrictemplate <class _Tp>
1623bdd1243dSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
1624349cc55cSDimitry Andricenable_if_t<
16250b57cec5SDimitry Andric    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
16260b57cec5SDimitry Andric    void
16270b57cec5SDimitry Andric>
16280b57cec5SDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
16290b57cec5SDimitry Andric{
16300b57cec5SDimitry Andric    __x.swap(__y);
16310b57cec5SDimitry Andric}
16320b57cec5SDimitry Andric
16330b57cec5SDimitry Andrictemplate <class _Tp>
16340b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
16350b57cec5SDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v)
16360b57cec5SDimitry Andric{
16370b57cec5SDimitry Andric    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
16380b57cec5SDimitry Andric}
16390b57cec5SDimitry Andric
16400b57cec5SDimitry Andrictemplate <class _Tp, class... _Args>
16410b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
16420b57cec5SDimitry Andricoptional<_Tp> make_optional(_Args&&... __args)
16430b57cec5SDimitry Andric{
16440b57cec5SDimitry Andric    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
16450b57cec5SDimitry Andric}
16460b57cec5SDimitry Andric
16470b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args>
16480b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
16490b57cec5SDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
16500b57cec5SDimitry Andric{
16510b57cec5SDimitry Andric    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
16520b57cec5SDimitry Andric}
16530b57cec5SDimitry Andric
16540b57cec5SDimitry Andrictemplate <class _Tp>
16550b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<
16560b57cec5SDimitry Andric    __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
16570b57cec5SDimitry Andric>
16580b57cec5SDimitry Andric{
1659fe6060f1SDimitry Andric#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1660fe6060f1SDimitry Andric    _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1661fe6060f1SDimitry Andric    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t        result_type;
1662fe6060f1SDimitry Andric#endif
16630b57cec5SDimitry Andric
16640b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1665fe6060f1SDimitry Andric    size_t operator()(const optional<_Tp>& __opt) const
16660b57cec5SDimitry Andric    {
16670b57cec5SDimitry Andric        return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
16680b57cec5SDimitry Andric    }
16690b57cec5SDimitry Andric};
16700b57cec5SDimitry Andric
16710b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
16720b57cec5SDimitry Andric
1673*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17
1674*06c3fb27SDimitry Andric
1675*06c3fb27SDimitry Andric_LIBCPP_POP_MACROS
16760b57cec5SDimitry Andric
1677bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
1678bdd1243dSDimitry Andric#  include <atomic>
1679bdd1243dSDimitry Andric#  include <climits>
1680bdd1243dSDimitry Andric#  include <concepts>
1681bdd1243dSDimitry Andric#  include <ctime>
1682bdd1243dSDimitry Andric#  include <iterator>
1683bdd1243dSDimitry Andric#  include <memory>
1684bdd1243dSDimitry Andric#  include <ratio>
1685bdd1243dSDimitry Andric#  include <tuple>
1686*06c3fb27SDimitry Andric#  include <type_traits>
1687bdd1243dSDimitry Andric#  include <typeinfo>
1688bdd1243dSDimitry Andric#  include <utility>
1689bdd1243dSDimitry Andric#  include <variant>
1690bdd1243dSDimitry Andric#endif
1691bdd1243dSDimitry Andric
16920b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL
1693