xref: /freebsd/contrib/llvm-project/libcxx/include/optional (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 {
1906c3fb27SDimitry Andric  // [optional.optional], class template optional
2006c3fb27SDimitry Andric  template <class T>
2106c3fb27SDimitry Andric    class optional;
220b57cec5SDimitry Andric
2306c3fb27SDimitry Andric  template<class T>
2406c3fb27SDimitry Andric    concept is-derived-from-optional = requires(const T& t) {       // exposition only
2506c3fb27SDimitry Andric      []<class U>(const optional<U>&){ }(t);
2606c3fb27SDimitry Andric    };
2706c3fb27SDimitry Andric
2806c3fb27SDimitry Andric  // [optional.nullopt], no-value state indicator
290b57cec5SDimitry Andric  struct nullopt_t{see below };
300b57cec5SDimitry Andric  inline constexpr nullopt_t nullopt(unspecified );
310b57cec5SDimitry Andric
3206c3fb27SDimitry Andric  // [optional.bad.access], class bad_optional_access
330b57cec5SDimitry Andric  class bad_optional_access;
340b57cec5SDimitry Andric
3506c3fb27SDimitry 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>&);
4806c3fb27SDimitry Andric  template<class T, three_way_comparable_with<T> U>
4906c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
5006c3fb27SDimitry Andric      operator<=>(const optional<T>&, const optional<U>&); // since C++20
510b57cec5SDimitry Andric
5206c3fb27SDimitry Andric  // [optional.nullops], comparison with nullopt
530b57cec5SDimitry Andric  template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
5406c3fb27SDimitry Andric  template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17
5506c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17
5606c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17
5706c3fb27SDimitry Andric  template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;  // until C++17
5806c3fb27SDimitry Andric  template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;  // until C++17
5906c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17
6006c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17
6106c3fb27SDimitry Andric  template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;  // until C++17
6206c3fb27SDimitry Andric  template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;  // until C++17
6306c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17
6406c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17
6506c3fb27SDimitry Andric  template<class T>
6606c3fb27SDimitry Andric    constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept;     // since C++20
670b57cec5SDimitry Andric
6806c3fb27SDimitry 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>&);
8106c3fb27SDimitry Andric  template<class T, class U>
8206c3fb27SDimitry Andric      requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U>
8306c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
8406c3fb27SDimitry Andric      operator<=>(const optional<T>&, const U&);                                       // since C++20
850b57cec5SDimitry Andric
8606c3fb27SDimitry Andric  // [optional.specalg], specialized algorithms
8706c3fb27SDimitry Andric  template<class T>
8806c3fb27SDimitry Andric    void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
8906c3fb27SDimitry Andric
9006c3fb27SDimitry Andric  template<class T>
9106c3fb27SDimitry 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
9706c3fb27SDimitry Andric  // [optional.hash], hash support
980b57cec5SDimitry Andric  template<class T> struct hash;
990b57cec5SDimitry Andric  template<class T> struct hash<optional<T>>;
1000b57cec5SDimitry Andric
10106c3fb27SDimitry Andric  template<class T>
10206c3fb27SDimitry Andric  class optional {
1030b57cec5SDimitry Andric  public:
1040b57cec5SDimitry Andric    using value_type = T;
1050b57cec5SDimitry Andric
10606c3fb27SDimitry 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);
11106c3fb27SDimitry Andric    template<class... Args>
11206c3fb27SDimitry 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
12206c3fb27SDimitry Andric    // [optional.dtor], destructor
123fe6060f1SDimitry Andric    ~optional(); // constexpr in C++20
1240b57cec5SDimitry Andric
12506c3fb27SDimitry 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
13306c3fb27SDimitry Andric    template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
1340b57cec5SDimitry Andric
13506c3fb27SDimitry Andric    // [optional.swap], swap
136fe6060f1SDimitry Andric    void swap(optional &) noexcept(see below ); // constexpr in C++20
1370b57cec5SDimitry Andric
13806c3fb27SDimitry 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
16606c3fb27SDimitry 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>
18206c3fb27SDimitry Andric#include <__compare/compare_three_way_result.h>
18306c3fb27SDimitry Andric#include <__compare/three_way_comparable.h>
1840eae32dcSDimitry Andric#include <__concepts/invocable.h>
185fe6060f1SDimitry Andric#include <__config>
186*5f757f3fSDimitry Andric#include <__exception/exception.h>
18781ad6265SDimitry Andric#include <__functional/hash.h>
18881ad6265SDimitry Andric#include <__functional/invoke.h>
18906c3fb27SDimitry Andric#include <__functional/reference_wrapper.h>
19081ad6265SDimitry Andric#include <__functional/unary_function.h>
19106c3fb27SDimitry Andric#include <__memory/addressof.h>
19281ad6265SDimitry Andric#include <__memory/construct_at.h>
19306c3fb27SDimitry Andric#include <__tuple/sfinae_helpers.h>
19406c3fb27SDimitry Andric#include <__type_traits/add_pointer.h>
19506c3fb27SDimitry Andric#include <__type_traits/conditional.h>
19606c3fb27SDimitry Andric#include <__type_traits/conjunction.h>
19706c3fb27SDimitry Andric#include <__type_traits/decay.h>
19806c3fb27SDimitry Andric#include <__type_traits/disjunction.h>
19906c3fb27SDimitry Andric#include <__type_traits/is_array.h>
20006c3fb27SDimitry Andric#include <__type_traits/is_assignable.h>
20106c3fb27SDimitry Andric#include <__type_traits/is_constructible.h>
20206c3fb27SDimitry Andric#include <__type_traits/is_convertible.h>
20306c3fb27SDimitry Andric#include <__type_traits/is_copy_assignable.h>
20406c3fb27SDimitry Andric#include <__type_traits/is_copy_constructible.h>
20506c3fb27SDimitry Andric#include <__type_traits/is_destructible.h>
20606c3fb27SDimitry Andric#include <__type_traits/is_move_assignable.h>
20706c3fb27SDimitry Andric#include <__type_traits/is_move_constructible.h>
20806c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_assignable.h>
20906c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_constructible.h>
21006c3fb27SDimitry Andric#include <__type_traits/is_object.h>
21106c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
21206c3fb27SDimitry Andric#include <__type_traits/is_scalar.h>
21306c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
21406c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_assignable.h>
21506c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_constructible.h>
21606c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h>
21706c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_assignable.h>
21806c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_constructible.h>
21906c3fb27SDimitry Andric#include <__type_traits/negation.h>
22006c3fb27SDimitry Andric#include <__type_traits/remove_const.h>
22106c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h>
22206c3fb27SDimitry Andric#include <__type_traits/remove_reference.h>
22306c3fb27SDimitry Andric#include <__utility/declval.h>
22481ad6265SDimitry Andric#include <__utility/forward.h>
22581ad6265SDimitry Andric#include <__utility/in_place.h>
22681ad6265SDimitry Andric#include <__utility/move.h>
22781ad6265SDimitry Andric#include <__utility/swap.h>
22806c3fb27SDimitry Andric#include <__verbose_abort>
2290b57cec5SDimitry Andric#include <initializer_list>
2300b57cec5SDimitry Andric#include <new>
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
24206c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS
24306c3fb27SDimitry Andric#include <__undef_macros>
24406c3fb27SDimitry Andric
2450b57cec5SDimitry Andricnamespace std  // purposefully not using versioning namespace
2460b57cec5SDimitry Andric{
2470b57cec5SDimitry Andric
24806c3fb27SDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
2490b57cec5SDimitry Andric    : public exception
2500b57cec5SDimitry Andric{
2510b57cec5SDimitry Andricpublic:
252*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT = default;
253*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT = default;
254*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default;
2550b57cec5SDimitry Andric    // Get the key function ~bad_optional_access() into the dylib
256bdd1243dSDimitry Andric    ~bad_optional_access() _NOEXCEPT override;
257bdd1243dSDimitry Andric    const char* what() const _NOEXCEPT override;
2580b57cec5SDimitry Andric};
2590b57cec5SDimitry Andric
2600eae32dcSDimitry Andric} // namespace std
2610b57cec5SDimitry Andric
26206c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric_LIBCPP_NORETURN
267*5f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI
2680b57cec5SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
2690b57cec5SDimitry Andricvoid __throw_bad_optional_access() {
27006c3fb27SDimitry Andric#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2710b57cec5SDimitry Andric        throw bad_optional_access();
2720b57cec5SDimitry Andric#else
27306c3fb27SDimitry Andric    _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode");
2740b57cec5SDimitry Andric#endif
2750b57cec5SDimitry Andric}
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andricstruct nullopt_t
2780b57cec5SDimitry Andric{
27906c3fb27SDimitry Andric    struct __secret_tag { explicit __secret_tag() = default; };
280*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
2810b57cec5SDimitry Andric};
2820b57cec5SDimitry Andric
283349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
2840b57cec5SDimitry Andric
2850eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {};
2860eae32dcSDimitry Andric
2870b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
2880b57cec5SDimitry Andricstruct __optional_destruct_base;
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andrictemplate <class _Tp>
2910b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, false>
2920b57cec5SDimitry Andric{
2930b57cec5SDimitry Andric    typedef _Tp value_type;
2940b57cec5SDimitry Andric    static_assert(is_object_v<value_type>,
2950b57cec5SDimitry Andric        "instantiation of optional with a non-object type is undefined behavior");
2960b57cec5SDimitry Andric    union
2970b57cec5SDimitry Andric    {
2980b57cec5SDimitry Andric        char __null_state_;
2990b57cec5SDimitry Andric        value_type __val_;
3000b57cec5SDimitry Andric    };
3010b57cec5SDimitry Andric    bool __engaged_;
3020b57cec5SDimitry Andric
303*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
304bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base()
3050b57cec5SDimitry Andric    {
3060b57cec5SDimitry Andric        if (__engaged_)
3070b57cec5SDimitry Andric            __val_.~value_type();
3080b57cec5SDimitry Andric    }
3090b57cec5SDimitry Andric
310*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3110b57cec5SDimitry Andric    constexpr __optional_destruct_base() noexcept
3120b57cec5SDimitry Andric        :  __null_state_(),
3130b57cec5SDimitry Andric           __engaged_(false) {}
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric    template <class... _Args>
316*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3170b57cec5SDimitry Andric    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
318*5f757f3fSDimitry Andric        :  __val_(std::forward<_Args>(__args)...),
3190b57cec5SDimitry Andric           __engaged_(true) {}
3200b57cec5SDimitry Andric
32106c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23
3220eae32dcSDimitry Andric  template <class _Fp, class... _Args>
3230eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
3240eae32dcSDimitry Andric  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
325*5f757f3fSDimitry Andric      : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
3260eae32dcSDimitry Andric#endif
3270eae32dcSDimitry Andric
328*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
329bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept
3300b57cec5SDimitry Andric    {
3310b57cec5SDimitry Andric        if (__engaged_)
3320b57cec5SDimitry Andric        {
3330b57cec5SDimitry Andric            __val_.~value_type();
3340b57cec5SDimitry Andric            __engaged_ = false;
3350b57cec5SDimitry Andric        }
3360b57cec5SDimitry Andric    }
3370b57cec5SDimitry Andric};
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andrictemplate <class _Tp>
3400b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, true>
3410b57cec5SDimitry Andric{
3420b57cec5SDimitry Andric    typedef _Tp value_type;
3430b57cec5SDimitry Andric    static_assert(is_object_v<value_type>,
3440b57cec5SDimitry Andric        "instantiation of optional with a non-object type is undefined behavior");
3450b57cec5SDimitry Andric    union
3460b57cec5SDimitry Andric    {
3470b57cec5SDimitry Andric        char __null_state_;
3480b57cec5SDimitry Andric        value_type __val_;
3490b57cec5SDimitry Andric    };
3500b57cec5SDimitry Andric    bool __engaged_;
3510b57cec5SDimitry Andric
352*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3530b57cec5SDimitry Andric    constexpr __optional_destruct_base() noexcept
3540b57cec5SDimitry Andric        :  __null_state_(),
3550b57cec5SDimitry Andric           __engaged_(false) {}
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric    template <class... _Args>
358*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3590b57cec5SDimitry Andric    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
360*5f757f3fSDimitry Andric        :  __val_(std::forward<_Args>(__args)...),
3610b57cec5SDimitry Andric           __engaged_(true) {}
3620b57cec5SDimitry Andric
36306c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 23
3640eae32dcSDimitry Andric  template <class _Fp, class... _Args>
3650eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
3660eae32dcSDimitry Andric  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
367*5f757f3fSDimitry Andric      : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
3680eae32dcSDimitry Andric#endif
3690eae32dcSDimitry Andric
370*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
371bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept
3720b57cec5SDimitry Andric    {
3730b57cec5SDimitry Andric        if (__engaged_)
3740b57cec5SDimitry Andric        {
3750b57cec5SDimitry Andric            __engaged_ = false;
3760b57cec5SDimitry Andric        }
3770b57cec5SDimitry Andric    }
3780b57cec5SDimitry Andric};
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value>
3810b57cec5SDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp>
3820b57cec5SDimitry Andric{
3830b57cec5SDimitry Andric    using __base = __optional_destruct_base<_Tp>;
3840b57cec5SDimitry Andric    using value_type = _Tp;
3850b57cec5SDimitry Andric    using __base::__base;
3860b57cec5SDimitry Andric
387*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3880b57cec5SDimitry Andric    constexpr bool has_value() const noexcept
3890b57cec5SDimitry Andric    {
3900b57cec5SDimitry Andric        return this->__engaged_;
3910b57cec5SDimitry Andric    }
3920b57cec5SDimitry Andric
393*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3940b57cec5SDimitry Andric    constexpr value_type& __get() & noexcept
3950b57cec5SDimitry Andric    {
3960b57cec5SDimitry Andric        return this->__val_;
3970b57cec5SDimitry Andric    }
398*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
3990b57cec5SDimitry Andric    constexpr const value_type& __get() const& noexcept
4000b57cec5SDimitry Andric    {
4010b57cec5SDimitry Andric        return this->__val_;
4020b57cec5SDimitry Andric    }
403*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
4040b57cec5SDimitry Andric    constexpr value_type&& __get() && noexcept
4050b57cec5SDimitry Andric    {
406*5f757f3fSDimitry Andric        return std::move(this->__val_);
4070b57cec5SDimitry Andric    }
408*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
4090b57cec5SDimitry Andric    constexpr const value_type&& __get() const&& noexcept
4100b57cec5SDimitry Andric    {
411*5f757f3fSDimitry Andric        return std::move(this->__val_);
4120b57cec5SDimitry Andric    }
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric    template <class... _Args>
415*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
416bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args)
4170b57cec5SDimitry Andric    {
41806c3fb27SDimitry Andric        _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
419*5f757f3fSDimitry Andric        std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...);
4200b57cec5SDimitry Andric        this->__engaged_ = true;
4210b57cec5SDimitry Andric    }
4220b57cec5SDimitry Andric
4230b57cec5SDimitry Andric    template <class _That>
424*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
425bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt)
4260b57cec5SDimitry Andric    {
4270b57cec5SDimitry Andric        if (__opt.has_value())
428*5f757f3fSDimitry Andric            __construct(std::forward<_That>(__opt).__get());
4290b57cec5SDimitry Andric    }
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric    template <class _That>
432*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
433bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt)
4340b57cec5SDimitry Andric    {
4350b57cec5SDimitry Andric        if (this->__engaged_ == __opt.has_value())
4360b57cec5SDimitry Andric        {
4370b57cec5SDimitry Andric            if (this->__engaged_)
438*5f757f3fSDimitry Andric                this->__val_ = std::forward<_That>(__opt).__get();
4390b57cec5SDimitry Andric        }
4400b57cec5SDimitry Andric        else
4410b57cec5SDimitry Andric        {
4420b57cec5SDimitry Andric            if (this->__engaged_)
4430b57cec5SDimitry Andric                this->reset();
4440b57cec5SDimitry Andric            else
445*5f757f3fSDimitry Andric                __construct(std::forward<_That>(__opt).__get());
4460b57cec5SDimitry Andric        }
4470b57cec5SDimitry Andric    }
4480b57cec5SDimitry Andric};
4490b57cec5SDimitry Andric
45081ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may
45181ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented
45281ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner.
4530b57cec5SDimitry Andrictemplate <class _Tp>
4540b57cec5SDimitry Andricstruct __optional_storage_base<_Tp, true>
4550b57cec5SDimitry Andric{
4560b57cec5SDimitry Andric    using value_type = _Tp;
4570b57cec5SDimitry Andric    using __raw_type = remove_reference_t<_Tp>;
4580b57cec5SDimitry Andric    __raw_type* __value_;
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andric    template <class _Up>
46106c3fb27SDimitry Andric    static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
462bdd1243dSDimitry Andric        using _RawUp = __libcpp_remove_reference_t<_Up>;
4630b57cec5SDimitry Andric        using _UpPtr = _RawUp*;
464bdd1243dSDimitry Andric        using _RawTp = __libcpp_remove_reference_t<_Tp>;
4650b57cec5SDimitry Andric        using _TpPtr = _RawTp*;
4660b57cec5SDimitry Andric        using _CheckLValueArg = integral_constant<bool,
4670b57cec5SDimitry Andric            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
4680b57cec5SDimitry Andric        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
469bdd1243dSDimitry Andric        ||  is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value
4700b57cec5SDimitry Andric        >;
4710b57cec5SDimitry Andric        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
4720b57cec5SDimitry Andric            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
4730b57cec5SDimitry Andric                is_convertible<_UpPtr, _TpPtr>::value);
4740b57cec5SDimitry Andric    }
4750b57cec5SDimitry Andric
476*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
4770b57cec5SDimitry Andric    constexpr __optional_storage_base() noexcept
4780b57cec5SDimitry Andric        :  __value_(nullptr) {}
4790b57cec5SDimitry Andric
4800b57cec5SDimitry Andric    template <class _UArg>
481*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
4820b57cec5SDimitry Andric    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
483*5f757f3fSDimitry Andric        :  __value_(std::addressof(__uarg))
4840b57cec5SDimitry Andric    {
4850b57cec5SDimitry Andric      static_assert(__can_bind_reference<_UArg>(),
4860b57cec5SDimitry Andric        "Attempted to construct a reference element in tuple from a "
4870b57cec5SDimitry Andric        "possible temporary");
4880b57cec5SDimitry Andric    }
4890b57cec5SDimitry Andric
490*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
491bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
4920b57cec5SDimitry Andric
493*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
4940b57cec5SDimitry Andric    constexpr bool has_value() const noexcept
4950b57cec5SDimitry Andric      { return __value_ != nullptr; }
4960b57cec5SDimitry Andric
497*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
4980b57cec5SDimitry Andric    constexpr value_type& __get() const& noexcept
4990b57cec5SDimitry Andric      { return *__value_; }
5000b57cec5SDimitry Andric
501*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5020b57cec5SDimitry Andric    constexpr value_type&& __get() const&& noexcept
503*5f757f3fSDimitry Andric      { return std::forward<value_type>(*__value_); }
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andric    template <class _UArg>
506*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
507bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val)
5080b57cec5SDimitry Andric    {
50906c3fb27SDimitry Andric        _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
5100b57cec5SDimitry Andric        static_assert(__can_bind_reference<_UArg>(),
5110b57cec5SDimitry Andric            "Attempted to construct a reference element in tuple from a "
5120b57cec5SDimitry Andric            "possible temporary");
513*5f757f3fSDimitry Andric        __value_ = std::addressof(__val);
5140b57cec5SDimitry Andric    }
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric    template <class _That>
517*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
518bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt)
5190b57cec5SDimitry Andric    {
5200b57cec5SDimitry Andric        if (__opt.has_value())
521*5f757f3fSDimitry Andric            __construct(std::forward<_That>(__opt).__get());
5220b57cec5SDimitry Andric    }
5230b57cec5SDimitry Andric
5240b57cec5SDimitry Andric    template <class _That>
525*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
526bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt)
5270b57cec5SDimitry Andric    {
5280b57cec5SDimitry Andric        if (has_value() == __opt.has_value())
5290b57cec5SDimitry Andric        {
5300b57cec5SDimitry Andric            if (has_value())
531*5f757f3fSDimitry Andric                *__value_ = std::forward<_That>(__opt).__get();
5320b57cec5SDimitry Andric        }
5330b57cec5SDimitry Andric        else
5340b57cec5SDimitry Andric        {
5350b57cec5SDimitry Andric            if (has_value())
5360b57cec5SDimitry Andric                reset();
5370b57cec5SDimitry Andric            else
538*5f757f3fSDimitry Andric                __construct(std::forward<_That>(__opt).__get());
5390b57cec5SDimitry Andric        }
5400b57cec5SDimitry Andric    }
5410b57cec5SDimitry Andric};
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
5440b57cec5SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp>
5450b57cec5SDimitry Andric{
5460b57cec5SDimitry Andric    using __optional_storage_base<_Tp>::__optional_storage_base;
5470b57cec5SDimitry Andric};
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andrictemplate <class _Tp>
5500b57cec5SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
5510b57cec5SDimitry Andric{
5520b57cec5SDimitry Andric    using __optional_storage_base<_Tp>::__optional_storage_base;
5530b57cec5SDimitry Andric
554*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5550b57cec5SDimitry Andric    __optional_copy_base() = default;
5560b57cec5SDimitry Andric
557*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
558bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt)
5590b57cec5SDimitry Andric    {
5600b57cec5SDimitry Andric        this->__construct_from(__opt);
5610b57cec5SDimitry Andric    }
5620b57cec5SDimitry Andric
563*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5640b57cec5SDimitry Andric    __optional_copy_base(__optional_copy_base&&) = default;
565*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5660b57cec5SDimitry Andric    __optional_copy_base& operator=(const __optional_copy_base&) = default;
567*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5680b57cec5SDimitry Andric    __optional_copy_base& operator=(__optional_copy_base&&) = default;
5690b57cec5SDimitry Andric};
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
5720b57cec5SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp>
5730b57cec5SDimitry Andric{
5740b57cec5SDimitry Andric    using __optional_copy_base<_Tp>::__optional_copy_base;
5750b57cec5SDimitry Andric};
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andrictemplate <class _Tp>
5780b57cec5SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
5790b57cec5SDimitry Andric{
5800b57cec5SDimitry Andric    using value_type = _Tp;
5810b57cec5SDimitry Andric    using __optional_copy_base<_Tp>::__optional_copy_base;
5820b57cec5SDimitry Andric
583*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5840b57cec5SDimitry Andric    __optional_move_base() = default;
585*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5860b57cec5SDimitry Andric    __optional_move_base(const __optional_move_base&) = default;
5870b57cec5SDimitry Andric
588*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
589bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_base(__optional_move_base&& __opt)
5900b57cec5SDimitry Andric        noexcept(is_nothrow_move_constructible_v<value_type>)
5910b57cec5SDimitry Andric    {
592*5f757f3fSDimitry Andric        this->__construct_from(std::move(__opt));
5930b57cec5SDimitry Andric    }
5940b57cec5SDimitry Andric
595*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5960b57cec5SDimitry Andric    __optional_move_base& operator=(const __optional_move_base&) = default;
597*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
5980b57cec5SDimitry Andric    __optional_move_base& operator=(__optional_move_base&&) = default;
5990b57cec5SDimitry Andric};
6000b57cec5SDimitry Andric
6010b57cec5SDimitry Andrictemplate <class _Tp, bool =
6020b57cec5SDimitry Andric    is_trivially_destructible<_Tp>::value &&
6030b57cec5SDimitry Andric    is_trivially_copy_constructible<_Tp>::value &&
6040b57cec5SDimitry Andric    is_trivially_copy_assignable<_Tp>::value>
6050b57cec5SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp>
6060b57cec5SDimitry Andric{
6070b57cec5SDimitry Andric    using __optional_move_base<_Tp>::__optional_move_base;
6080b57cec5SDimitry Andric};
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andrictemplate <class _Tp>
6110b57cec5SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
6120b57cec5SDimitry Andric{
6130b57cec5SDimitry Andric    using __optional_move_base<_Tp>::__optional_move_base;
6140b57cec5SDimitry Andric
615*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6160b57cec5SDimitry Andric    __optional_copy_assign_base() = default;
617*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6180b57cec5SDimitry Andric    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
619*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6200b57cec5SDimitry Andric    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
6210b57cec5SDimitry Andric
622*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
623bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
6240b57cec5SDimitry Andric    {
6250b57cec5SDimitry Andric        this->__assign_from(__opt);
6260b57cec5SDimitry Andric        return *this;
6270b57cec5SDimitry Andric    }
6280b57cec5SDimitry Andric
629*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6300b57cec5SDimitry Andric    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
6310b57cec5SDimitry Andric};
6320b57cec5SDimitry Andric
6330b57cec5SDimitry Andrictemplate <class _Tp, bool =
6340b57cec5SDimitry Andric    is_trivially_destructible<_Tp>::value &&
6350b57cec5SDimitry Andric    is_trivially_move_constructible<_Tp>::value &&
6360b57cec5SDimitry Andric    is_trivially_move_assignable<_Tp>::value>
6370b57cec5SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
6380b57cec5SDimitry Andric{
6390b57cec5SDimitry Andric    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
6400b57cec5SDimitry Andric};
6410b57cec5SDimitry Andric
6420b57cec5SDimitry Andrictemplate <class _Tp>
6430b57cec5SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
6440b57cec5SDimitry Andric{
6450b57cec5SDimitry Andric    using value_type = _Tp;
6460b57cec5SDimitry Andric    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
6470b57cec5SDimitry Andric
648*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6490b57cec5SDimitry Andric    __optional_move_assign_base() = default;
650*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6510b57cec5SDimitry Andric    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
652*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6530b57cec5SDimitry Andric    __optional_move_assign_base(__optional_move_assign_base&&) = default;
654*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
6550b57cec5SDimitry Andric    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
6560b57cec5SDimitry Andric
657*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
658bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
6590b57cec5SDimitry Andric        noexcept(is_nothrow_move_assignable_v<value_type> &&
6600b57cec5SDimitry Andric                 is_nothrow_move_constructible_v<value_type>)
6610b57cec5SDimitry Andric    {
662*5f757f3fSDimitry Andric        this->__assign_from(std::move(__opt));
6630b57cec5SDimitry Andric        return *this;
6640b57cec5SDimitry Andric    }
6650b57cec5SDimitry Andric};
6660b57cec5SDimitry Andric
6670b57cec5SDimitry Andrictemplate <class _Tp>
6680b57cec5SDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
6690b57cec5SDimitry Andric    is_copy_constructible<_Tp>::value,
6700b57cec5SDimitry Andric    is_move_constructible<_Tp>::value
6710b57cec5SDimitry Andric>;
6720b57cec5SDimitry Andric
6730b57cec5SDimitry Andrictemplate <class _Tp>
6740b57cec5SDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base<
6750b57cec5SDimitry Andric    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
6760b57cec5SDimitry Andric    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
6770b57cec5SDimitry Andric>;
6780b57cec5SDimitry Andric
6790b57cec5SDimitry Andrictemplate<class _Tp>
6800eae32dcSDimitry Andricclass optional;
68106c3fb27SDimitry Andric
68206c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
68306c3fb27SDimitry Andric
68406c3fb27SDimitry Andrictemplate <class _Tp>
68506c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); };
68606c3fb27SDimitry Andric
68706c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
68806c3fb27SDimitry Andric
6890eae32dcSDimitry Andrictemplate <class _Tp>
6900eae32dcSDimitry Andricstruct __is_std_optional : false_type {};
6910eae32dcSDimitry Andrictemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
6920eae32dcSDimitry Andric
6930eae32dcSDimitry Andrictemplate <class _Tp>
69406c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional
6950b57cec5SDimitry Andric    : private __optional_move_assign_base<_Tp>
6960b57cec5SDimitry Andric    , private __optional_sfinae_ctor_base_t<_Tp>
6970b57cec5SDimitry Andric    , private __optional_sfinae_assign_base_t<_Tp>
6980b57cec5SDimitry Andric{
6990b57cec5SDimitry Andric    using __base = __optional_move_assign_base<_Tp>;
7000b57cec5SDimitry Andricpublic:
7010b57cec5SDimitry Andric    using value_type = _Tp;
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andricprivate:
7040b57cec5SDimitry Andric     // Disable the reference extension using this static assert.
705bdd1243dSDimitry Andric    static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,
7060b57cec5SDimitry Andric        "instantiation of optional with in_place_t is ill-formed");
707bdd1243dSDimitry Andric    static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>,
7080b57cec5SDimitry Andric        "instantiation of optional with nullopt_t is ill-formed");
7090b57cec5SDimitry Andric    static_assert(!is_reference_v<value_type>,
7100b57cec5SDimitry Andric        "instantiation of optional with a reference type is ill-formed");
7110b57cec5SDimitry Andric    static_assert(is_destructible_v<value_type>,
7120b57cec5SDimitry Andric        "instantiation of optional with a non-destructible type is ill-formed");
7130b57cec5SDimitry Andric    static_assert(!is_array_v<value_type>,
7140b57cec5SDimitry Andric        "instantiation of optional with an array type is ill-formed");
7150b57cec5SDimitry Andric
7160b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from _Up
7170b57cec5SDimitry Andric    struct _CheckOptionalArgsConstructor {
7180b57cec5SDimitry Andric      template <class _Up>
71906c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
7200b57cec5SDimitry Andric          return is_constructible_v<_Tp, _Up&&> &&
7210b57cec5SDimitry Andric                 is_convertible_v<_Up&&, _Tp>;
7220b57cec5SDimitry Andric      }
7230b57cec5SDimitry Andric
7240b57cec5SDimitry Andric      template <class _Up>
72506c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
7260b57cec5SDimitry Andric          return is_constructible_v<_Tp, _Up&&> &&
7270b57cec5SDimitry Andric                 !is_convertible_v<_Up&&, _Tp>;
7280b57cec5SDimitry Andric      }
7290b57cec5SDimitry Andric    };
7300b57cec5SDimitry Andric    template <class _Up>
7310b57cec5SDimitry Andric    using _CheckOptionalArgsCtor = _If<
732bdd1243dSDimitry Andric        _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value &&
733*5f757f3fSDimitry Andric        _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
734*5f757f3fSDimitry Andric        (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::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>
75906c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
7600b57cec5SDimitry Andric          return is_convertible<_QUp, _Tp>::value &&
761*5f757f3fSDimitry Andric                 (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
7620b57cec5SDimitry Andric      }
7630b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
76406c3fb27SDimitry Andric      _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
7650b57cec5SDimitry Andric          return !is_convertible<_QUp, _Tp>::value &&
766*5f757f3fSDimitry Andric                 (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
7670b57cec5SDimitry Andric      }
7680b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
76906c3fb27SDimitry 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
799*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
800*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default;
801*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default;
802*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI 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    >
811*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
8120b57cec5SDimitry Andric    constexpr explicit optional(_InPlaceT, _Args&&... __args)
813*5f757f3fSDimitry Andric        : __base(in_place, std::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    >
818*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
8190b57cec5SDimitry Andric    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
820*5f757f3fSDimitry Andric        : __base(in_place, __il, std::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>
825*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
8260b57cec5SDimitry Andric    constexpr optional(_Up&& __v)
827*5f757f3fSDimitry Andric        : __base(in_place, std::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>
832*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
8330b57cec5SDimitry Andric    constexpr explicit optional(_Up&& __v)
834*5f757f3fSDimitry Andric        : __base(in_place, std::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>
840*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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>
848*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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>
858*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
859bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v)
8600b57cec5SDimitry Andric    {
861*5f757f3fSDimitry Andric        this->__construct_from(std::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>
866*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
867bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v)
8680b57cec5SDimitry Andric    {
869*5f757f3fSDimitry Andric        this->__construct_from(std::move(__v));
8700b57cec5SDimitry Andric    }
8710b57cec5SDimitry Andric
87206c3fb27SDimitry 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)
876*5f757f3fSDimitry Andric      : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {
8770eae32dcSDimitry Andric  }
8780eae32dcSDimitry Andric#endif
8790eae32dcSDimitry Andric
880*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
881bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept
8820b57cec5SDimitry Andric    {
8830b57cec5SDimitry Andric        reset();
8840b57cec5SDimitry Andric        return *this;
8850b57cec5SDimitry Andric    }
8860b57cec5SDimitry Andric
88706c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
88806c3fb27SDimitry 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             >
903*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
904bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
9050b57cec5SDimitry Andric    operator=(_Up&& __v)
9060b57cec5SDimitry Andric    {
9070b57cec5SDimitry Andric        if (this->has_value())
908*5f757f3fSDimitry Andric            this->__get() = std::forward<_Up>(__v);
9090b57cec5SDimitry Andric        else
910*5f757f3fSDimitry Andric            this->__construct(std::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>
918*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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>
930*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
931bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
9320b57cec5SDimitry Andric    operator=(optional<_Up>&& __v)
9330b57cec5SDimitry Andric    {
934*5f757f3fSDimitry Andric        this->__assign_from(std::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             >
944*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
945bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp &
9460b57cec5SDimitry Andric    emplace(_Args&&... __args)
9470b57cec5SDimitry Andric    {
9480b57cec5SDimitry Andric        reset();
949*5f757f3fSDimitry Andric        this->__construct(std::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             >
959*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
960bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp &
9610b57cec5SDimitry Andric    emplace(initializer_list<_Up> __il, _Args&&... __args)
9620b57cec5SDimitry Andric    {
9630b57cec5SDimitry Andric        reset();
964*5f757f3fSDimitry Andric        this->__construct(__il, std::forward<_Args>(__args)...);
9650b57cec5SDimitry Andric        return this->__get();
9660b57cec5SDimitry Andric    }
9670b57cec5SDimitry Andric
968*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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        {
975*5f757f3fSDimitry Andric            using std::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            {
983*5f757f3fSDimitry Andric                __opt.__construct(std::move(this->__get()));
9840b57cec5SDimitry Andric                reset();
9850b57cec5SDimitry Andric            }
9860b57cec5SDimitry Andric            else
9870b57cec5SDimitry Andric            {
988*5f757f3fSDimitry Andric                this->__construct(std::move(__opt.__get()));
9890b57cec5SDimitry Andric                __opt.reset();
9900b57cec5SDimitry Andric            }
9910b57cec5SDimitry Andric        }
9920b57cec5SDimitry Andric    }
9930b57cec5SDimitry Andric
994*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
9950b57cec5SDimitry Andric    constexpr
9960b57cec5SDimitry Andric    add_pointer_t<value_type const>
9970b57cec5SDimitry Andric    operator->() const
9980b57cec5SDimitry Andric    {
99906c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
1000*5f757f3fSDimitry Andric        return std::addressof(this->__get());
10010b57cec5SDimitry Andric    }
10020b57cec5SDimitry Andric
1003*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
10040b57cec5SDimitry Andric    constexpr
10050b57cec5SDimitry Andric    add_pointer_t<value_type>
10060b57cec5SDimitry Andric    operator->()
10070b57cec5SDimitry Andric    {
100806c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
1009*5f757f3fSDimitry Andric        return std::addressof(this->__get());
10100b57cec5SDimitry Andric    }
10110b57cec5SDimitry Andric
1012*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
10130b57cec5SDimitry Andric    constexpr
10140b57cec5SDimitry Andric    const value_type&
1015fe6060f1SDimitry Andric    operator*() const& noexcept
10160b57cec5SDimitry Andric    {
101706c3fb27SDimitry 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
1021*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
10220b57cec5SDimitry Andric    constexpr
10230b57cec5SDimitry Andric    value_type&
1024fe6060f1SDimitry Andric    operator*() & noexcept
10250b57cec5SDimitry Andric    {
102606c3fb27SDimitry 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
1030*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
10310b57cec5SDimitry Andric    constexpr
10320b57cec5SDimitry Andric    value_type&&
1033fe6060f1SDimitry Andric    operator*() && noexcept
10340b57cec5SDimitry Andric    {
103506c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
1036*5f757f3fSDimitry Andric        return std::move(this->__get());
10370b57cec5SDimitry Andric    }
10380b57cec5SDimitry Andric
1039*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
10400b57cec5SDimitry Andric    constexpr
10410b57cec5SDimitry Andric    const value_type&&
1042fe6060f1SDimitry Andric    operator*() const&& noexcept
10430b57cec5SDimitry Andric    {
104406c3fb27SDimitry Andric        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
1045*5f757f3fSDimitry Andric        return std::move(this->__get());
10460b57cec5SDimitry Andric    }
10470b57cec5SDimitry Andric
1048*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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
1054*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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
1063*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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
1072*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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();
1078*5f757f3fSDimitry Andric        return std::move(this->__get());
10790b57cec5SDimitry Andric    }
10800b57cec5SDimitry Andric
1081*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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();
1087*5f757f3fSDimitry Andric        return std::move(this->__get());
10880b57cec5SDimitry Andric    }
10890b57cec5SDimitry Andric
10900b57cec5SDimitry Andric    template <class _Up>
1091*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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() :
1099*5f757f3fSDimitry Andric                                  static_cast<value_type>(std::forward<_Up>(__v));
11000b57cec5SDimitry Andric    }
11010b57cec5SDimitry Andric
11020b57cec5SDimitry Andric    template <class _Up>
1103*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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");
1110*5f757f3fSDimitry Andric        return this->has_value() ? std::move(this->__get()) :
1111*5f757f3fSDimitry Andric                                  static_cast<value_type>(std::forward<_Up>(__v));
11120b57cec5SDimitry Andric    }
11130b57cec5SDimitry Andric
111406c3fb27SDimitry 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)
1122*5f757f3fSDimitry Andric      return std::invoke(std::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)
1133*5f757f3fSDimitry Andric      return std::invoke(std::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)
1144*5f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), std::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)
1155*5f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), std::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)
1170*5f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::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)
1185*5f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::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)
1200*5f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::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)
1215*5f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::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;
1226*5f757f3fSDimitry Andric    return std::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)
1235*5f757f3fSDimitry Andric      return std::move(*this);
1236*5f757f3fSDimitry Andric    return std::forward<_Func>(__f)();
12370eae32dcSDimitry Andric  }
123806c3fb27SDimitry 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>
1250*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1266*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1282*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1298*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1314*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1330*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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
134506c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
134606c3fb27SDimitry Andric
134706c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up>
134806c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
134906c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) {
135006c3fb27SDimitry Andric    if (__x && __y)
135106c3fb27SDimitry Andric        return *__x <=> *__y;
135206c3fb27SDimitry Andric    return __x.has_value() <=> __y.has_value();
135306c3fb27SDimitry Andric}
135406c3fb27SDimitry Andric
135506c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 20
135606c3fb27SDimitry Andric
13570b57cec5SDimitry Andric// Comparisons with nullopt
13580b57cec5SDimitry Andrictemplate <class _Tp>
1359*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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
136606c3fb27SDimitry Andric#if _LIBCPP_STD_VER <= 17
136706c3fb27SDimitry Andric
13680b57cec5SDimitry Andrictemplate <class _Tp>
1369*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1377*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1385*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1393*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1401*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1409*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1417*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1425*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1433*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1441*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1449*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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
145606c3fb27SDimitry Andric#else // _LIBCPP_STD_VER <= 17
145706c3fb27SDimitry Andric
145806c3fb27SDimitry Andrictemplate <class _Tp>
145906c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept {
146006c3fb27SDimitry Andric    return __x.has_value() <=> false;
146106c3fb27SDimitry Andric}
146206c3fb27SDimitry Andric
146306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER <= 17
146406c3fb27SDimitry Andric
14650b57cec5SDimitry Andric// Comparisons with T
14660b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1467*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1479*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1491*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1503*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1515*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1527*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1539*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1551*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1563*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1575*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1587*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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>
1599*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI 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
161006c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 20
161106c3fb27SDimitry Andric
161206c3fb27SDimitry Andrictemplate <class _Tp, class _Up>
161306c3fb27SDimitry Andric  requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up>
161406c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
161506c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) {
161606c3fb27SDimitry Andric    return __x.has_value() ? *__x <=> __v : strong_ordering::less;
161706c3fb27SDimitry Andric}
161806c3fb27SDimitry Andric
161906c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 20
162006c3fb27SDimitry Andric
16210b57cec5SDimitry Andric
16220b57cec5SDimitry Andrictemplate <class _Tp>
1623*5f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _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>
1634*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr
16350b57cec5SDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v)
16360b57cec5SDimitry Andric{
1637*5f757f3fSDimitry Andric    return optional<decay_t<_Tp>>(std::forward<_Tp>(__v));
16380b57cec5SDimitry Andric}
16390b57cec5SDimitry Andric
16400b57cec5SDimitry Andrictemplate <class _Tp, class... _Args>
1641*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr
16420b57cec5SDimitry Andricoptional<_Tp> make_optional(_Args&&... __args)
16430b57cec5SDimitry Andric{
1644*5f757f3fSDimitry Andric    return optional<_Tp>(in_place, std::forward<_Args>(__args)...);
16450b57cec5SDimitry Andric}
16460b57cec5SDimitry Andric
16470b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args>
1648*5f757f3fSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr
16490b57cec5SDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
16500b57cec5SDimitry Andric{
1651*5f757f3fSDimitry Andric    return optional<_Tp>(in_place, __il, std::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
1664*5f757f3fSDimitry Andric    _LIBCPP_HIDE_FROM_ABI
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
167306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17
167406c3fb27SDimitry Andric
167506c3fb27SDimitry 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>
1685*5f757f3fSDimitry Andric#  include <stdexcept>
1686bdd1243dSDimitry Andric#  include <tuple>
168706c3fb27SDimitry Andric#  include <type_traits>
1688bdd1243dSDimitry Andric#  include <typeinfo>
1689bdd1243dSDimitry Andric#  include <utility>
1690bdd1243dSDimitry Andric#  include <variant>
1691bdd1243dSDimitry Andric#endif
1692bdd1243dSDimitry Andric
16930b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL
1694