xref: /freebsd/contrib/llvm-project/libcxx/include/optional (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 {
190b57cec5SDimitry Andric  // 23.6.3, optional for object types
200b57cec5SDimitry Andric  template <class T> class optional;
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric  // 23.6.4, no-value state indicator
230b57cec5SDimitry Andric  struct nullopt_t{see below };
240b57cec5SDimitry Andric  inline constexpr nullopt_t nullopt(unspecified );
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric  // 23.6.5, class bad_optional_access
270b57cec5SDimitry Andric  class bad_optional_access;
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric  // 23.6.6, relational operators
300b57cec5SDimitry Andric  template <class T, class U>
310b57cec5SDimitry Andric  constexpr bool operator==(const optional<T>&, const optional<U>&);
320b57cec5SDimitry Andric  template <class T, class U>
330b57cec5SDimitry Andric  constexpr bool operator!=(const optional<T>&, const optional<U>&);
340b57cec5SDimitry Andric  template <class T, class U>
350b57cec5SDimitry Andric  constexpr bool operator<(const optional<T>&, const optional<U>&);
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
430b57cec5SDimitry Andric  // 23.6.7 comparison with nullopt
440b57cec5SDimitry Andric  template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
450b57cec5SDimitry Andric  template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
460b57cec5SDimitry Andric  template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
470b57cec5SDimitry Andric  template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
480b57cec5SDimitry Andric  template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
490b57cec5SDimitry Andric  template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
500b57cec5SDimitry Andric  template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
510b57cec5SDimitry Andric  template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
520b57cec5SDimitry Andric  template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
530b57cec5SDimitry Andric  template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
540b57cec5SDimitry Andric  template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
550b57cec5SDimitry Andric  template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric  // 23.6.8, comparison with T
580b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
590b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
600b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
610b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
620b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
630b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
640b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
650b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
660b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
670b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
680b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
690b57cec5SDimitry Andric  template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric  // 23.6.9, specialized algorithms
72fe6060f1SDimitry Andric  template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
730b57cec5SDimitry Andric  template <class T> constexpr optional<see below > make_optional(T&&);
740b57cec5SDimitry Andric  template <class T, class... Args>
750b57cec5SDimitry Andric    constexpr optional<T> make_optional(Args&&... args);
760b57cec5SDimitry Andric  template <class T, class U, class... Args>
770b57cec5SDimitry Andric    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric  // 23.6.10, hash support
800b57cec5SDimitry Andric  template <class T> struct hash;
810b57cec5SDimitry Andric  template <class T> struct hash<optional<T>>;
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric  template <class T> class optional {
840b57cec5SDimitry Andric  public:
850b57cec5SDimitry Andric    using value_type = T;
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric    // 23.6.3.1, constructors
880b57cec5SDimitry Andric    constexpr optional() noexcept;
890b57cec5SDimitry Andric    constexpr optional(nullopt_t) noexcept;
90*bdd1243dSDimitry Andric    constexpr optional(const optional &);
91*bdd1243dSDimitry Andric    constexpr optional(optional &&) noexcept(see below);
920b57cec5SDimitry Andric    template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
930b57cec5SDimitry Andric    template <class U, class... Args>
940b57cec5SDimitry Andric      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
950b57cec5SDimitry Andric    template <class U = T>
9681ad6265SDimitry Andric      constexpr explicit(see-below) optional(U &&);
970b57cec5SDimitry Andric    template <class U>
9881ad6265SDimitry Andric      explicit(see-below) optional(const optional<U> &);         // constexpr in C++20
990b57cec5SDimitry Andric    template <class U>
10081ad6265SDimitry Andric      explicit(see-below) optional(optional<U> &&);              // constexpr in C++20
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric    // 23.6.3.2, destructor
103fe6060f1SDimitry Andric    ~optional(); // constexpr in C++20
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric    // 23.6.3.3, assignment
106fe6060f1SDimitry Andric    optional &operator=(nullopt_t) noexcept;                     // constexpr in C++20
107*bdd1243dSDimitry Andric    constexpr optional &operator=(const optional &);
108*bdd1243dSDimitry Andric    constexpr optional &operator=(optional &&) noexcept(see below);
109fe6060f1SDimitry Andric    template <class U = T> optional &operator=(U &&);            // constexpr in C++20
110fe6060f1SDimitry Andric    template <class U> optional &operator=(const optional<U> &); // constexpr in C++20
111fe6060f1SDimitry Andric    template <class U> optional &operator=(optional<U> &&);      // constexpr in C++20
112fe6060f1SDimitry Andric    template <class... Args> T& emplace(Args &&...);             // constexpr in C++20
1130b57cec5SDimitry Andric    template <class U, class... Args>
114fe6060f1SDimitry Andric      T& emplace(initializer_list<U>, Args &&...);               // constexpr in C++20
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric    // 23.6.3.4, swap
117fe6060f1SDimitry Andric    void swap(optional &) noexcept(see below ); // constexpr in C++20
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric    // 23.6.3.5, observers
1200b57cec5SDimitry Andric    constexpr T const *operator->() const;
1210b57cec5SDimitry Andric    constexpr T *operator->();
1220b57cec5SDimitry Andric    constexpr T const &operator*() const &;
1230b57cec5SDimitry Andric    constexpr T &operator*() &;
1240b57cec5SDimitry Andric    constexpr T &&operator*() &&;
1250b57cec5SDimitry Andric    constexpr const T &&operator*() const &&;
1260b57cec5SDimitry Andric    constexpr explicit operator bool() const noexcept;
1270b57cec5SDimitry Andric    constexpr bool has_value() const noexcept;
1280b57cec5SDimitry Andric    constexpr T const &value() const &;
1290b57cec5SDimitry Andric    constexpr T &value() &;
1300b57cec5SDimitry Andric    constexpr T &&value() &&;
1310b57cec5SDimitry Andric    constexpr const T &&value() const &&;
1320b57cec5SDimitry Andric    template <class U> constexpr T value_or(U &&) const &;
1330b57cec5SDimitry Andric    template <class U> constexpr T value_or(U &&) &&;
1340b57cec5SDimitry Andric
1350eae32dcSDimitry Andric    // [optional.monadic], monadic operations
1360eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &;         // since C++23
1370eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &&;        // since C++23
1380eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&;    // since C++23
1390eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&&;   // since C++23
1400eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &;        // since C++23
1410eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &&;       // since C++23
1420eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&;   // since C++23
1430eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&&;  // since C++23
1440eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) &&;     // since C++23
1450eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) const&; // since C++23
1460eae32dcSDimitry Andric
1470b57cec5SDimitry Andric    // 23.6.3.6, modifiers
148fe6060f1SDimitry Andric    void reset() noexcept; // constexpr in C++20
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric  private:
1510b57cec5SDimitry Andric    T *val; // exposition only
1520b57cec5SDimitry Andric  };
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andrictemplate<class T>
1550b57cec5SDimitry Andric  optional(T) -> optional<T>;
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric} // namespace std
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andric*/
1600b57cec5SDimitry Andric
16181ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
162e8d8bef9SDimitry Andric#include <__availability>
1630eae32dcSDimitry Andric#include <__concepts/invocable.h>
164fe6060f1SDimitry Andric#include <__config>
16581ad6265SDimitry Andric#include <__functional/hash.h>
16681ad6265SDimitry Andric#include <__functional/invoke.h>
16781ad6265SDimitry Andric#include <__functional/unary_function.h>
16881ad6265SDimitry Andric#include <__memory/construct_at.h>
169*bdd1243dSDimitry Andric#include <__tuple_dir/sfinae_helpers.h>
17081ad6265SDimitry Andric#include <__utility/forward.h>
17181ad6265SDimitry Andric#include <__utility/in_place.h>
17281ad6265SDimitry Andric#include <__utility/move.h>
17381ad6265SDimitry Andric#include <__utility/swap.h>
1740b57cec5SDimitry Andric#include <initializer_list>
1750b57cec5SDimitry Andric#include <new>
1760b57cec5SDimitry Andric#include <stdexcept>
1770b57cec5SDimitry Andric#include <type_traits>
1780b57cec5SDimitry Andric#include <version>
1790b57cec5SDimitry Andric
18081ad6265SDimitry Andric// standard-mandated includes
181*bdd1243dSDimitry Andric
182*bdd1243dSDimitry Andric// [optional.syn]
18381ad6265SDimitry Andric#include <compare>
18481ad6265SDimitry Andric
1850b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1860b57cec5SDimitry Andric#  pragma GCC system_header
1870b57cec5SDimitry Andric#endif
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andricnamespace std  // purposefully not using versioning namespace
1900b57cec5SDimitry Andric{
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
1930b57cec5SDimitry Andric    : public exception
1940b57cec5SDimitry Andric{
1950b57cec5SDimitry Andricpublic:
1960b57cec5SDimitry Andric    // Get the key function ~bad_optional_access() into the dylib
197*bdd1243dSDimitry Andric    ~bad_optional_access() _NOEXCEPT override;
198*bdd1243dSDimitry Andric    const char* what() const _NOEXCEPT override;
1990b57cec5SDimitry Andric};
2000b57cec5SDimitry Andric
2010eae32dcSDimitry Andric} // namespace std
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 14
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric_LIBCPP_NORETURN
2080b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
2090b57cec5SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
2100b57cec5SDimitry Andricvoid __throw_bad_optional_access() {
2110b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS
2120b57cec5SDimitry Andric        throw bad_optional_access();
2130b57cec5SDimitry Andric#else
2140b57cec5SDimitry Andric        _VSTD::abort();
2150b57cec5SDimitry Andric#endif
2160b57cec5SDimitry Andric}
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andricstruct nullopt_t
2190b57cec5SDimitry Andric{
2200b57cec5SDimitry Andric    struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
2210b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
2220b57cec5SDimitry Andric};
2230b57cec5SDimitry Andric
224349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
2250b57cec5SDimitry Andric
2260eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {};
2270eae32dcSDimitry Andric
2280b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
2290b57cec5SDimitry Andricstruct __optional_destruct_base;
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andrictemplate <class _Tp>
2320b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, false>
2330b57cec5SDimitry Andric{
2340b57cec5SDimitry Andric    typedef _Tp value_type;
2350b57cec5SDimitry Andric    static_assert(is_object_v<value_type>,
2360b57cec5SDimitry Andric        "instantiation of optional with a non-object type is undefined behavior");
2370b57cec5SDimitry Andric    union
2380b57cec5SDimitry Andric    {
2390b57cec5SDimitry Andric        char __null_state_;
2400b57cec5SDimitry Andric        value_type __val_;
2410b57cec5SDimitry Andric    };
2420b57cec5SDimitry Andric    bool __engaged_;
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
245*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base()
2460b57cec5SDimitry Andric    {
2470b57cec5SDimitry Andric        if (__engaged_)
2480b57cec5SDimitry Andric            __val_.~value_type();
2490b57cec5SDimitry Andric    }
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2520b57cec5SDimitry Andric    constexpr __optional_destruct_base() noexcept
2530b57cec5SDimitry Andric        :  __null_state_(),
2540b57cec5SDimitry Andric           __engaged_(false) {}
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric    template <class... _Args>
2570b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2580b57cec5SDimitry Andric    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
2590b57cec5SDimitry Andric        :  __val_(_VSTD::forward<_Args>(__args)...),
2600b57cec5SDimitry Andric           __engaged_(true) {}
2610b57cec5SDimitry Andric
2620eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20
2630eae32dcSDimitry Andric  template <class _Fp, class... _Args>
2640eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
2650eae32dcSDimitry Andric  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
2660eae32dcSDimitry Andric      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
2670eae32dcSDimitry Andric#endif
2680eae32dcSDimitry Andric
2690b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
270*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept
2710b57cec5SDimitry Andric    {
2720b57cec5SDimitry Andric        if (__engaged_)
2730b57cec5SDimitry Andric        {
2740b57cec5SDimitry Andric            __val_.~value_type();
2750b57cec5SDimitry Andric            __engaged_ = false;
2760b57cec5SDimitry Andric        }
2770b57cec5SDimitry Andric    }
2780b57cec5SDimitry Andric};
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andrictemplate <class _Tp>
2810b57cec5SDimitry Andricstruct __optional_destruct_base<_Tp, true>
2820b57cec5SDimitry Andric{
2830b57cec5SDimitry Andric    typedef _Tp value_type;
2840b57cec5SDimitry Andric    static_assert(is_object_v<value_type>,
2850b57cec5SDimitry Andric        "instantiation of optional with a non-object type is undefined behavior");
2860b57cec5SDimitry Andric    union
2870b57cec5SDimitry Andric    {
2880b57cec5SDimitry Andric        char __null_state_;
2890b57cec5SDimitry Andric        value_type __val_;
2900b57cec5SDimitry Andric    };
2910b57cec5SDimitry Andric    bool __engaged_;
2920b57cec5SDimitry Andric
2930b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2940b57cec5SDimitry Andric    constexpr __optional_destruct_base() noexcept
2950b57cec5SDimitry Andric        :  __null_state_(),
2960b57cec5SDimitry Andric           __engaged_(false) {}
2970b57cec5SDimitry Andric
2980b57cec5SDimitry Andric    template <class... _Args>
2990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3000b57cec5SDimitry Andric    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
3010b57cec5SDimitry Andric        :  __val_(_VSTD::forward<_Args>(__args)...),
3020b57cec5SDimitry Andric           __engaged_(true) {}
3030b57cec5SDimitry Andric
3040eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20
3050eae32dcSDimitry Andric  template <class _Fp, class... _Args>
3060eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
3070eae32dcSDimitry Andric  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3080eae32dcSDimitry Andric      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
3090eae32dcSDimitry Andric#endif
3100eae32dcSDimitry Andric
3110b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
312*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept
3130b57cec5SDimitry Andric    {
3140b57cec5SDimitry Andric        if (__engaged_)
3150b57cec5SDimitry Andric        {
3160b57cec5SDimitry Andric            __engaged_ = false;
3170b57cec5SDimitry Andric        }
3180b57cec5SDimitry Andric    }
3190b57cec5SDimitry Andric};
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value>
3220b57cec5SDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp>
3230b57cec5SDimitry Andric{
3240b57cec5SDimitry Andric    using __base = __optional_destruct_base<_Tp>;
3250b57cec5SDimitry Andric    using value_type = _Tp;
3260b57cec5SDimitry Andric    using __base::__base;
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3290b57cec5SDimitry Andric    constexpr bool has_value() const noexcept
3300b57cec5SDimitry Andric    {
3310b57cec5SDimitry Andric        return this->__engaged_;
3320b57cec5SDimitry Andric    }
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3350b57cec5SDimitry Andric    constexpr value_type& __get() & noexcept
3360b57cec5SDimitry Andric    {
3370b57cec5SDimitry Andric        return this->__val_;
3380b57cec5SDimitry Andric    }
3390b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3400b57cec5SDimitry Andric    constexpr const value_type& __get() const& noexcept
3410b57cec5SDimitry Andric    {
3420b57cec5SDimitry Andric        return this->__val_;
3430b57cec5SDimitry Andric    }
3440b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3450b57cec5SDimitry Andric    constexpr value_type&& __get() && noexcept
3460b57cec5SDimitry Andric    {
3470b57cec5SDimitry Andric        return _VSTD::move(this->__val_);
3480b57cec5SDimitry Andric    }
3490b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3500b57cec5SDimitry Andric    constexpr const value_type&& __get() const&& noexcept
3510b57cec5SDimitry Andric    {
3520b57cec5SDimitry Andric        return _VSTD::move(this->__val_);
3530b57cec5SDimitry Andric    }
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric    template <class... _Args>
3560b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
357*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args)
3580b57cec5SDimitry Andric    {
3590b57cec5SDimitry Andric        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
360fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17
361fe6060f1SDimitry Andric        _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
362fe6060f1SDimitry Andric#else
3630b57cec5SDimitry Andric        ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
364fe6060f1SDimitry Andric#endif
3650b57cec5SDimitry Andric        this->__engaged_ = true;
3660b57cec5SDimitry Andric    }
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric    template <class _That>
3690b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
370*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt)
3710b57cec5SDimitry Andric    {
3720b57cec5SDimitry Andric        if (__opt.has_value())
3730b57cec5SDimitry Andric            __construct(_VSTD::forward<_That>(__opt).__get());
3740b57cec5SDimitry Andric    }
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric    template <class _That>
3770b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
378*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt)
3790b57cec5SDimitry Andric    {
3800b57cec5SDimitry Andric        if (this->__engaged_ == __opt.has_value())
3810b57cec5SDimitry Andric        {
3820b57cec5SDimitry Andric            if (this->__engaged_)
3830b57cec5SDimitry Andric                this->__val_ = _VSTD::forward<_That>(__opt).__get();
3840b57cec5SDimitry Andric        }
3850b57cec5SDimitry Andric        else
3860b57cec5SDimitry Andric        {
3870b57cec5SDimitry Andric            if (this->__engaged_)
3880b57cec5SDimitry Andric                this->reset();
3890b57cec5SDimitry Andric            else
3900b57cec5SDimitry Andric                __construct(_VSTD::forward<_That>(__opt).__get());
3910b57cec5SDimitry Andric        }
3920b57cec5SDimitry Andric    }
3930b57cec5SDimitry Andric};
3940b57cec5SDimitry Andric
39581ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may
39681ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented
39781ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner.
3980b57cec5SDimitry Andrictemplate <class _Tp>
3990b57cec5SDimitry Andricstruct __optional_storage_base<_Tp, true>
4000b57cec5SDimitry Andric{
4010b57cec5SDimitry Andric    using value_type = _Tp;
4020b57cec5SDimitry Andric    using __raw_type = remove_reference_t<_Tp>;
4030b57cec5SDimitry Andric    __raw_type* __value_;
4040b57cec5SDimitry Andric
4050b57cec5SDimitry Andric    template <class _Up>
4060b57cec5SDimitry Andric    static constexpr bool __can_bind_reference() {
407*bdd1243dSDimitry Andric        using _RawUp = __libcpp_remove_reference_t<_Up>;
4080b57cec5SDimitry Andric        using _UpPtr = _RawUp*;
409*bdd1243dSDimitry Andric        using _RawTp = __libcpp_remove_reference_t<_Tp>;
4100b57cec5SDimitry Andric        using _TpPtr = _RawTp*;
4110b57cec5SDimitry Andric        using _CheckLValueArg = integral_constant<bool,
4120b57cec5SDimitry Andric            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
4130b57cec5SDimitry Andric        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
414*bdd1243dSDimitry Andric        ||  is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value
4150b57cec5SDimitry Andric        >;
4160b57cec5SDimitry Andric        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
4170b57cec5SDimitry Andric            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
4180b57cec5SDimitry Andric                is_convertible<_UpPtr, _TpPtr>::value);
4190b57cec5SDimitry Andric    }
4200b57cec5SDimitry Andric
4210b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4220b57cec5SDimitry Andric    constexpr __optional_storage_base() noexcept
4230b57cec5SDimitry Andric        :  __value_(nullptr) {}
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric    template <class _UArg>
4260b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4270b57cec5SDimitry Andric    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
4280b57cec5SDimitry Andric        :  __value_(_VSTD::addressof(__uarg))
4290b57cec5SDimitry Andric    {
4300b57cec5SDimitry Andric      static_assert(__can_bind_reference<_UArg>(),
4310b57cec5SDimitry Andric        "Attempted to construct a reference element in tuple from a "
4320b57cec5SDimitry Andric        "possible temporary");
4330b57cec5SDimitry Andric    }
4340b57cec5SDimitry Andric
4350b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
436*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
4370b57cec5SDimitry Andric
4380b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4390b57cec5SDimitry Andric    constexpr bool has_value() const noexcept
4400b57cec5SDimitry Andric      { return __value_ != nullptr; }
4410b57cec5SDimitry Andric
4420b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4430b57cec5SDimitry Andric    constexpr value_type& __get() const& noexcept
4440b57cec5SDimitry Andric      { return *__value_; }
4450b57cec5SDimitry Andric
4460b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4470b57cec5SDimitry Andric    constexpr value_type&& __get() const&& noexcept
4480b57cec5SDimitry Andric      { return _VSTD::forward<value_type>(*__value_); }
4490b57cec5SDimitry Andric
4500b57cec5SDimitry Andric    template <class _UArg>
4510b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
452*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val)
4530b57cec5SDimitry Andric    {
4540b57cec5SDimitry Andric        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
4550b57cec5SDimitry Andric        static_assert(__can_bind_reference<_UArg>(),
4560b57cec5SDimitry Andric            "Attempted to construct a reference element in tuple from a "
4570b57cec5SDimitry Andric            "possible temporary");
4580b57cec5SDimitry Andric        __value_ = _VSTD::addressof(__val);
4590b57cec5SDimitry Andric    }
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric    template <class _That>
4620b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
463*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt)
4640b57cec5SDimitry Andric    {
4650b57cec5SDimitry Andric        if (__opt.has_value())
4660b57cec5SDimitry Andric            __construct(_VSTD::forward<_That>(__opt).__get());
4670b57cec5SDimitry Andric    }
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric    template <class _That>
4700b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
471*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt)
4720b57cec5SDimitry Andric    {
4730b57cec5SDimitry Andric        if (has_value() == __opt.has_value())
4740b57cec5SDimitry Andric        {
4750b57cec5SDimitry Andric            if (has_value())
4760b57cec5SDimitry Andric                *__value_ = _VSTD::forward<_That>(__opt).__get();
4770b57cec5SDimitry Andric        }
4780b57cec5SDimitry Andric        else
4790b57cec5SDimitry Andric        {
4800b57cec5SDimitry Andric            if (has_value())
4810b57cec5SDimitry Andric                reset();
4820b57cec5SDimitry Andric            else
4830b57cec5SDimitry Andric                __construct(_VSTD::forward<_That>(__opt).__get());
4840b57cec5SDimitry Andric        }
4850b57cec5SDimitry Andric    }
4860b57cec5SDimitry Andric};
4870b57cec5SDimitry Andric
4880b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
4890b57cec5SDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp>
4900b57cec5SDimitry Andric{
4910b57cec5SDimitry Andric    using __optional_storage_base<_Tp>::__optional_storage_base;
4920b57cec5SDimitry Andric};
4930b57cec5SDimitry Andric
4940b57cec5SDimitry Andrictemplate <class _Tp>
4950b57cec5SDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
4960b57cec5SDimitry Andric{
4970b57cec5SDimitry Andric    using __optional_storage_base<_Tp>::__optional_storage_base;
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5000b57cec5SDimitry Andric    __optional_copy_base() = default;
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
503*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt)
5040b57cec5SDimitry Andric    {
5050b57cec5SDimitry Andric        this->__construct_from(__opt);
5060b57cec5SDimitry Andric    }
5070b57cec5SDimitry Andric
5080b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5090b57cec5SDimitry Andric    __optional_copy_base(__optional_copy_base&&) = default;
5100b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5110b57cec5SDimitry Andric    __optional_copy_base& operator=(const __optional_copy_base&) = default;
5120b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5130b57cec5SDimitry Andric    __optional_copy_base& operator=(__optional_copy_base&&) = default;
5140b57cec5SDimitry Andric};
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
5170b57cec5SDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp>
5180b57cec5SDimitry Andric{
5190b57cec5SDimitry Andric    using __optional_copy_base<_Tp>::__optional_copy_base;
5200b57cec5SDimitry Andric};
5210b57cec5SDimitry Andric
5220b57cec5SDimitry Andrictemplate <class _Tp>
5230b57cec5SDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
5240b57cec5SDimitry Andric{
5250b57cec5SDimitry Andric    using value_type = _Tp;
5260b57cec5SDimitry Andric    using __optional_copy_base<_Tp>::__optional_copy_base;
5270b57cec5SDimitry Andric
5280b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5290b57cec5SDimitry Andric    __optional_move_base() = default;
5300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5310b57cec5SDimitry Andric    __optional_move_base(const __optional_move_base&) = default;
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
534*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_base(__optional_move_base&& __opt)
5350b57cec5SDimitry Andric        noexcept(is_nothrow_move_constructible_v<value_type>)
5360b57cec5SDimitry Andric    {
5370b57cec5SDimitry Andric        this->__construct_from(_VSTD::move(__opt));
5380b57cec5SDimitry Andric    }
5390b57cec5SDimitry Andric
5400b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5410b57cec5SDimitry Andric    __optional_move_base& operator=(const __optional_move_base&) = default;
5420b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5430b57cec5SDimitry Andric    __optional_move_base& operator=(__optional_move_base&&) = default;
5440b57cec5SDimitry Andric};
5450b57cec5SDimitry Andric
5460b57cec5SDimitry Andrictemplate <class _Tp, bool =
5470b57cec5SDimitry Andric    is_trivially_destructible<_Tp>::value &&
5480b57cec5SDimitry Andric    is_trivially_copy_constructible<_Tp>::value &&
5490b57cec5SDimitry Andric    is_trivially_copy_assignable<_Tp>::value>
5500b57cec5SDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp>
5510b57cec5SDimitry Andric{
5520b57cec5SDimitry Andric    using __optional_move_base<_Tp>::__optional_move_base;
5530b57cec5SDimitry Andric};
5540b57cec5SDimitry Andric
5550b57cec5SDimitry Andrictemplate <class _Tp>
5560b57cec5SDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
5570b57cec5SDimitry Andric{
5580b57cec5SDimitry Andric    using __optional_move_base<_Tp>::__optional_move_base;
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5610b57cec5SDimitry Andric    __optional_copy_assign_base() = default;
5620b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5630b57cec5SDimitry Andric    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
5640b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5650b57cec5SDimitry Andric    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
5660b57cec5SDimitry Andric
5670b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
568*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
5690b57cec5SDimitry Andric    {
5700b57cec5SDimitry Andric        this->__assign_from(__opt);
5710b57cec5SDimitry Andric        return *this;
5720b57cec5SDimitry Andric    }
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5750b57cec5SDimitry Andric    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
5760b57cec5SDimitry Andric};
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andrictemplate <class _Tp, bool =
5790b57cec5SDimitry Andric    is_trivially_destructible<_Tp>::value &&
5800b57cec5SDimitry Andric    is_trivially_move_constructible<_Tp>::value &&
5810b57cec5SDimitry Andric    is_trivially_move_assignable<_Tp>::value>
5820b57cec5SDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
5830b57cec5SDimitry Andric{
5840b57cec5SDimitry Andric    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
5850b57cec5SDimitry Andric};
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andrictemplate <class _Tp>
5880b57cec5SDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
5890b57cec5SDimitry Andric{
5900b57cec5SDimitry Andric    using value_type = _Tp;
5910b57cec5SDimitry Andric    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
5920b57cec5SDimitry Andric
5930b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5940b57cec5SDimitry Andric    __optional_move_assign_base() = default;
5950b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5960b57cec5SDimitry Andric    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
5970b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
5980b57cec5SDimitry Andric    __optional_move_assign_base(__optional_move_assign_base&&) = default;
5990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
6000b57cec5SDimitry Andric    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
603*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
6040b57cec5SDimitry Andric        noexcept(is_nothrow_move_assignable_v<value_type> &&
6050b57cec5SDimitry Andric                 is_nothrow_move_constructible_v<value_type>)
6060b57cec5SDimitry Andric    {
6070b57cec5SDimitry Andric        this->__assign_from(_VSTD::move(__opt));
6080b57cec5SDimitry Andric        return *this;
6090b57cec5SDimitry Andric    }
6100b57cec5SDimitry Andric};
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andrictemplate <class _Tp>
6130b57cec5SDimitry Andricusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
6140b57cec5SDimitry Andric    is_copy_constructible<_Tp>::value,
6150b57cec5SDimitry Andric    is_move_constructible<_Tp>::value
6160b57cec5SDimitry Andric>;
6170b57cec5SDimitry Andric
6180b57cec5SDimitry Andrictemplate <class _Tp>
6190b57cec5SDimitry Andricusing __optional_sfinae_assign_base_t = __sfinae_assign_base<
6200b57cec5SDimitry Andric    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
6210b57cec5SDimitry Andric    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
6220b57cec5SDimitry Andric>;
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andrictemplate<class _Tp>
6250eae32dcSDimitry Andricclass optional;
6260eae32dcSDimitry Andrictemplate <class _Tp>
6270eae32dcSDimitry Andricstruct __is_std_optional : false_type {};
6280eae32dcSDimitry Andrictemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
6290eae32dcSDimitry Andric
6300eae32dcSDimitry Andrictemplate <class _Tp>
6310b57cec5SDimitry Andricclass optional
6320b57cec5SDimitry Andric    : private __optional_move_assign_base<_Tp>
6330b57cec5SDimitry Andric    , private __optional_sfinae_ctor_base_t<_Tp>
6340b57cec5SDimitry Andric    , private __optional_sfinae_assign_base_t<_Tp>
6350b57cec5SDimitry Andric{
6360b57cec5SDimitry Andric    using __base = __optional_move_assign_base<_Tp>;
6370b57cec5SDimitry Andricpublic:
6380b57cec5SDimitry Andric    using value_type = _Tp;
6390b57cec5SDimitry Andric
6400b57cec5SDimitry Andricprivate:
6410b57cec5SDimitry Andric     // Disable the reference extension using this static assert.
642*bdd1243dSDimitry Andric    static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,
6430b57cec5SDimitry Andric        "instantiation of optional with in_place_t is ill-formed");
644*bdd1243dSDimitry Andric    static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>,
6450b57cec5SDimitry Andric        "instantiation of optional with nullopt_t is ill-formed");
6460b57cec5SDimitry Andric    static_assert(!is_reference_v<value_type>,
6470b57cec5SDimitry Andric        "instantiation of optional with a reference type is ill-formed");
6480b57cec5SDimitry Andric    static_assert(is_destructible_v<value_type>,
6490b57cec5SDimitry Andric        "instantiation of optional with a non-destructible type is ill-formed");
6500b57cec5SDimitry Andric    static_assert(!is_array_v<value_type>,
6510b57cec5SDimitry Andric        "instantiation of optional with an array type is ill-formed");
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from _Up
6540b57cec5SDimitry Andric    struct _CheckOptionalArgsConstructor {
6550b57cec5SDimitry Andric      template <class _Up>
6560b57cec5SDimitry Andric      static constexpr bool __enable_implicit() {
6570b57cec5SDimitry Andric          return is_constructible_v<_Tp, _Up&&> &&
6580b57cec5SDimitry Andric                 is_convertible_v<_Up&&, _Tp>;
6590b57cec5SDimitry Andric      }
6600b57cec5SDimitry Andric
6610b57cec5SDimitry Andric      template <class _Up>
6620b57cec5SDimitry Andric      static constexpr bool __enable_explicit() {
6630b57cec5SDimitry Andric          return is_constructible_v<_Tp, _Up&&> &&
6640b57cec5SDimitry Andric                 !is_convertible_v<_Up&&, _Tp>;
6650b57cec5SDimitry Andric      }
6660b57cec5SDimitry Andric    };
6670b57cec5SDimitry Andric    template <class _Up>
6680b57cec5SDimitry Andric    using _CheckOptionalArgsCtor = _If<
669*bdd1243dSDimitry Andric        _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value &&
670*bdd1243dSDimitry Andric        _IsNotSame<__remove_cvref_t<_Up>, optional>::value,
6710b57cec5SDimitry Andric        _CheckOptionalArgsConstructor,
6720b57cec5SDimitry Andric        __check_tuple_constructor_fail
6730b57cec5SDimitry Andric    >;
6740b57cec5SDimitry Andric    template <class _QualUp>
6750b57cec5SDimitry Andric    struct _CheckOptionalLikeConstructor {
6760b57cec5SDimitry Andric      template <class _Up, class _Opt = optional<_Up>>
6770b57cec5SDimitry Andric      using __check_constructible_from_opt = _Or<
6780b57cec5SDimitry Andric          is_constructible<_Tp, _Opt&>,
6790b57cec5SDimitry Andric          is_constructible<_Tp, _Opt const&>,
6800b57cec5SDimitry Andric          is_constructible<_Tp, _Opt&&>,
6810b57cec5SDimitry Andric          is_constructible<_Tp, _Opt const&&>,
6820b57cec5SDimitry Andric          is_convertible<_Opt&, _Tp>,
6830b57cec5SDimitry Andric          is_convertible<_Opt const&, _Tp>,
6840b57cec5SDimitry Andric          is_convertible<_Opt&&, _Tp>,
6850b57cec5SDimitry Andric          is_convertible<_Opt const&&, _Tp>
6860b57cec5SDimitry Andric      >;
6870b57cec5SDimitry Andric      template <class _Up, class _Opt = optional<_Up>>
6880b57cec5SDimitry Andric      using __check_assignable_from_opt = _Or<
6890b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt&>,
6900b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt const&>,
6910b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt&&>,
6920b57cec5SDimitry Andric          is_assignable<_Tp&, _Opt const&&>
6930b57cec5SDimitry Andric      >;
6940b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
6950b57cec5SDimitry Andric      static constexpr bool __enable_implicit() {
6960b57cec5SDimitry Andric          return is_convertible<_QUp, _Tp>::value &&
6970b57cec5SDimitry Andric              !__check_constructible_from_opt<_Up>::value;
6980b57cec5SDimitry Andric      }
6990b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
7000b57cec5SDimitry Andric      static constexpr bool __enable_explicit() {
7010b57cec5SDimitry Andric          return !is_convertible<_QUp, _Tp>::value &&
7020b57cec5SDimitry Andric              !__check_constructible_from_opt<_Up>::value;
7030b57cec5SDimitry Andric      }
7040b57cec5SDimitry Andric      template <class _Up, class _QUp = _QualUp>
7050b57cec5SDimitry Andric      static constexpr bool __enable_assign() {
706e8d8bef9SDimitry Andric          // Construction and assignability of _QUp to _Tp has already been
7070b57cec5SDimitry Andric          // checked.
7080b57cec5SDimitry Andric          return !__check_constructible_from_opt<_Up>::value &&
7090b57cec5SDimitry Andric              !__check_assignable_from_opt<_Up>::value;
7100b57cec5SDimitry Andric      }
7110b57cec5SDimitry Andric    };
7120b57cec5SDimitry Andric
7130b57cec5SDimitry Andric    template <class _Up, class _QualUp>
7140b57cec5SDimitry Andric    using _CheckOptionalLikeCtor = _If<
7150b57cec5SDimitry Andric      _And<
7160b57cec5SDimitry Andric         _IsNotSame<_Up, _Tp>,
7170b57cec5SDimitry Andric          is_constructible<_Tp, _QualUp>
7180b57cec5SDimitry Andric      >::value,
7190b57cec5SDimitry Andric      _CheckOptionalLikeConstructor<_QualUp>,
7200b57cec5SDimitry Andric      __check_tuple_constructor_fail
7210b57cec5SDimitry Andric    >;
7220b57cec5SDimitry Andric    template <class _Up, class _QualUp>
7230b57cec5SDimitry Andric    using _CheckOptionalLikeAssign = _If<
7240b57cec5SDimitry Andric      _And<
7250b57cec5SDimitry Andric          _IsNotSame<_Up, _Tp>,
7260b57cec5SDimitry Andric          is_constructible<_Tp, _QualUp>,
7270b57cec5SDimitry Andric          is_assignable<_Tp&, _QualUp>
7280b57cec5SDimitry Andric      >::value,
7290b57cec5SDimitry Andric      _CheckOptionalLikeConstructor<_QualUp>,
7300b57cec5SDimitry Andric      __check_tuple_constructor_fail
7310b57cec5SDimitry Andric    >;
7320eae32dcSDimitry Andric
7330b57cec5SDimitry Andricpublic:
7340b57cec5SDimitry Andric
7350b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
7360b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
7370b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
7380b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
7390b57cec5SDimitry Andric
740349cc55cSDimitry Andric    template <class _InPlaceT, class... _Args, class = enable_if_t<
7410b57cec5SDimitry Andric          _And<
7420b57cec5SDimitry Andric              _IsSame<_InPlaceT, in_place_t>,
7430b57cec5SDimitry Andric              is_constructible<value_type, _Args...>
7440b57cec5SDimitry Andric            >::value
7450b57cec5SDimitry Andric        >
7460b57cec5SDimitry Andric    >
7470b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7480b57cec5SDimitry Andric    constexpr explicit optional(_InPlaceT, _Args&&... __args)
7490b57cec5SDimitry Andric        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
7500b57cec5SDimitry Andric
751349cc55cSDimitry Andric    template <class _Up, class... _Args, class = enable_if_t<
7520b57cec5SDimitry Andric        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
7530b57cec5SDimitry Andric    >
7540b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7550b57cec5SDimitry Andric    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
7560b57cec5SDimitry Andric        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
7570b57cec5SDimitry Andric
758349cc55cSDimitry Andric    template <class _Up = value_type, enable_if_t<
7590b57cec5SDimitry Andric        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
7600b57cec5SDimitry Andric    , int> = 0>
7610b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7620b57cec5SDimitry Andric    constexpr optional(_Up&& __v)
7630b57cec5SDimitry Andric        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
7640b57cec5SDimitry Andric
765349cc55cSDimitry Andric    template <class _Up, enable_if_t<
7660b57cec5SDimitry Andric        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
7670b57cec5SDimitry Andric    , int> = 0>
7680b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
7690b57cec5SDimitry Andric    constexpr explicit optional(_Up&& __v)
7700b57cec5SDimitry Andric        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from const optional<_Up>&
773349cc55cSDimitry Andric    template <class _Up, enable_if_t<
7740b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
7750b57cec5SDimitry Andric    , int> = 0>
7760b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
777*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v)
7780b57cec5SDimitry Andric    {
7790b57cec5SDimitry Andric        this->__construct_from(__v);
7800b57cec5SDimitry Andric    }
781349cc55cSDimitry Andric    template <class _Up, enable_if_t<
7820b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
7830b57cec5SDimitry Andric    , int> = 0>
7840b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
785*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v)
7860b57cec5SDimitry Andric    {
7870b57cec5SDimitry Andric        this->__construct_from(__v);
7880b57cec5SDimitry Andric    }
7890b57cec5SDimitry Andric
7900b57cec5SDimitry Andric    // LWG2756: conditionally explicit conversion from optional<_Up>&&
791349cc55cSDimitry Andric    template <class _Up, enable_if_t<
7920b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
7930b57cec5SDimitry Andric    , int> = 0>
7940b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
795*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v)
7960b57cec5SDimitry Andric    {
7970b57cec5SDimitry Andric        this->__construct_from(_VSTD::move(__v));
7980b57cec5SDimitry Andric    }
799349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8000b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
8010b57cec5SDimitry Andric    , int> = 0>
8020b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
803*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v)
8040b57cec5SDimitry Andric    {
8050b57cec5SDimitry Andric        this->__construct_from(_VSTD::move(__v));
8060b57cec5SDimitry Andric    }
8070b57cec5SDimitry Andric
8080eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20
8090eae32dcSDimitry Andric  template<class _Fp, class... _Args>
8100eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
8110eae32dcSDimitry Andric  constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
8120eae32dcSDimitry Andric      : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
8130eae32dcSDimitry Andric  }
8140eae32dcSDimitry Andric#endif
8150eae32dcSDimitry Andric
8160b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
817*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept
8180b57cec5SDimitry Andric    {
8190b57cec5SDimitry Andric        reset();
8200b57cec5SDimitry Andric        return *this;
8210b57cec5SDimitry Andric    }
8220b57cec5SDimitry Andric
823*bdd1243dSDimitry Andric    constexpr optional& operator=(const optional&) = default;
824*bdd1243dSDimitry Andric    constexpr optional& operator=(optional&&) = default;
8250b57cec5SDimitry Andric
8260b57cec5SDimitry Andric    // LWG2756
8270b57cec5SDimitry Andric    template <class _Up = value_type,
828349cc55cSDimitry Andric              class = enable_if_t<
8290b57cec5SDimitry Andric                      _And<
830*bdd1243dSDimitry Andric                          _IsNotSame<__remove_cvref_t<_Up>, optional>,
8310b57cec5SDimitry Andric                          _Or<
832*bdd1243dSDimitry Andric                              _IsNotSame<__remove_cvref_t<_Up>, value_type>,
8330b57cec5SDimitry Andric                              _Not<is_scalar<value_type>>
8340b57cec5SDimitry Andric                          >,
8350b57cec5SDimitry Andric                          is_constructible<value_type, _Up>,
8360b57cec5SDimitry Andric                          is_assignable<value_type&, _Up>
8370b57cec5SDimitry Andric                      >::value>
8380b57cec5SDimitry Andric             >
8390b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
840*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
8410b57cec5SDimitry Andric    operator=(_Up&& __v)
8420b57cec5SDimitry Andric    {
8430b57cec5SDimitry Andric        if (this->has_value())
8440b57cec5SDimitry Andric            this->__get() = _VSTD::forward<_Up>(__v);
8450b57cec5SDimitry Andric        else
8460b57cec5SDimitry Andric            this->__construct(_VSTD::forward<_Up>(__v));
8470b57cec5SDimitry Andric        return *this;
8480b57cec5SDimitry Andric    }
8490b57cec5SDimitry Andric
8500b57cec5SDimitry Andric    // LWG2756
851349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8520b57cec5SDimitry Andric        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
8530b57cec5SDimitry Andric    , int> = 0>
8540b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
855*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
8560b57cec5SDimitry Andric    operator=(const optional<_Up>& __v)
8570b57cec5SDimitry Andric    {
8580b57cec5SDimitry Andric        this->__assign_from(__v);
8590b57cec5SDimitry Andric        return *this;
8600b57cec5SDimitry Andric    }
8610b57cec5SDimitry Andric
8620b57cec5SDimitry Andric    // LWG2756
863349cc55cSDimitry Andric    template <class _Up, enable_if_t<
8640b57cec5SDimitry Andric        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
8650b57cec5SDimitry Andric    , int> = 0>
8660b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
867*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 optional&
8680b57cec5SDimitry Andric    operator=(optional<_Up>&& __v)
8690b57cec5SDimitry Andric    {
8700b57cec5SDimitry Andric        this->__assign_from(_VSTD::move(__v));
8710b57cec5SDimitry Andric        return *this;
8720b57cec5SDimitry Andric    }
8730b57cec5SDimitry Andric
8740b57cec5SDimitry Andric    template <class... _Args,
875349cc55cSDimitry Andric              class = enable_if_t
8760b57cec5SDimitry Andric                      <
8770b57cec5SDimitry Andric                          is_constructible_v<value_type, _Args...>
8780b57cec5SDimitry Andric                      >
8790b57cec5SDimitry Andric             >
8800b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
881*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp &
8820b57cec5SDimitry Andric    emplace(_Args&&... __args)
8830b57cec5SDimitry Andric    {
8840b57cec5SDimitry Andric        reset();
8850b57cec5SDimitry Andric        this->__construct(_VSTD::forward<_Args>(__args)...);
8860b57cec5SDimitry Andric        return this->__get();
8870b57cec5SDimitry Andric    }
8880b57cec5SDimitry Andric
8890b57cec5SDimitry Andric    template <class _Up, class... _Args,
890349cc55cSDimitry Andric              class = enable_if_t
8910b57cec5SDimitry Andric                      <
8920b57cec5SDimitry Andric                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
8930b57cec5SDimitry Andric                      >
8940b57cec5SDimitry Andric             >
8950b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
896*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp &
8970b57cec5SDimitry Andric    emplace(initializer_list<_Up> __il, _Args&&... __args)
8980b57cec5SDimitry Andric    {
8990b57cec5SDimitry Andric        reset();
9000b57cec5SDimitry Andric        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
9010b57cec5SDimitry Andric        return this->__get();
9020b57cec5SDimitry Andric    }
9030b57cec5SDimitry Andric
9040b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
905*bdd1243dSDimitry Andric    _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional& __opt)
9060b57cec5SDimitry Andric        noexcept(is_nothrow_move_constructible_v<value_type> &&
9070b57cec5SDimitry Andric                 is_nothrow_swappable_v<value_type>)
9080b57cec5SDimitry Andric    {
9090b57cec5SDimitry Andric        if (this->has_value() == __opt.has_value())
9100b57cec5SDimitry Andric        {
9110b57cec5SDimitry Andric            using _VSTD::swap;
9120b57cec5SDimitry Andric            if (this->has_value())
9130b57cec5SDimitry Andric                swap(this->__get(), __opt.__get());
9140b57cec5SDimitry Andric        }
9150b57cec5SDimitry Andric        else
9160b57cec5SDimitry Andric        {
9170b57cec5SDimitry Andric            if (this->has_value())
9180b57cec5SDimitry Andric            {
9190b57cec5SDimitry Andric                __opt.__construct(_VSTD::move(this->__get()));
9200b57cec5SDimitry Andric                reset();
9210b57cec5SDimitry Andric            }
9220b57cec5SDimitry Andric            else
9230b57cec5SDimitry Andric            {
9240b57cec5SDimitry Andric                this->__construct(_VSTD::move(__opt.__get()));
9250b57cec5SDimitry Andric                __opt.reset();
9260b57cec5SDimitry Andric            }
9270b57cec5SDimitry Andric        }
9280b57cec5SDimitry Andric    }
9290b57cec5SDimitry Andric
9300b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9310b57cec5SDimitry Andric    constexpr
9320b57cec5SDimitry Andric    add_pointer_t<value_type const>
9330b57cec5SDimitry Andric    operator->() const
9340b57cec5SDimitry Andric    {
935fe6060f1SDimitry Andric        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
9360b57cec5SDimitry Andric        return _VSTD::addressof(this->__get());
9370b57cec5SDimitry Andric    }
9380b57cec5SDimitry Andric
9390b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9400b57cec5SDimitry Andric    constexpr
9410b57cec5SDimitry Andric    add_pointer_t<value_type>
9420b57cec5SDimitry Andric    operator->()
9430b57cec5SDimitry Andric    {
944fe6060f1SDimitry Andric        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
9450b57cec5SDimitry Andric        return _VSTD::addressof(this->__get());
9460b57cec5SDimitry Andric    }
9470b57cec5SDimitry Andric
9480b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9490b57cec5SDimitry Andric    constexpr
9500b57cec5SDimitry Andric    const value_type&
951fe6060f1SDimitry Andric    operator*() const& noexcept
9520b57cec5SDimitry Andric    {
953fe6060f1SDimitry Andric        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
9540b57cec5SDimitry Andric        return this->__get();
9550b57cec5SDimitry Andric    }
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9580b57cec5SDimitry Andric    constexpr
9590b57cec5SDimitry Andric    value_type&
960fe6060f1SDimitry Andric    operator*() & noexcept
9610b57cec5SDimitry Andric    {
962fe6060f1SDimitry Andric        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
9630b57cec5SDimitry Andric        return this->__get();
9640b57cec5SDimitry Andric    }
9650b57cec5SDimitry Andric
9660b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9670b57cec5SDimitry Andric    constexpr
9680b57cec5SDimitry Andric    value_type&&
969fe6060f1SDimitry Andric    operator*() && noexcept
9700b57cec5SDimitry Andric    {
971fe6060f1SDimitry Andric        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
9720b57cec5SDimitry Andric        return _VSTD::move(this->__get());
9730b57cec5SDimitry Andric    }
9740b57cec5SDimitry Andric
9750b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9760b57cec5SDimitry Andric    constexpr
9770b57cec5SDimitry Andric    const value_type&&
978fe6060f1SDimitry Andric    operator*() const&& noexcept
9790b57cec5SDimitry Andric    {
980fe6060f1SDimitry Andric        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
9810b57cec5SDimitry Andric        return _VSTD::move(this->__get());
9820b57cec5SDimitry Andric    }
9830b57cec5SDimitry Andric
9840b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9850b57cec5SDimitry Andric    constexpr explicit operator bool() const noexcept { return has_value(); }
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric    using __base::has_value;
9880b57cec5SDimitry Andric    using __base::__get;
9890b57cec5SDimitry Andric
9900b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
9910b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
9920b57cec5SDimitry Andric    constexpr value_type const& value() const&
9930b57cec5SDimitry Andric    {
9940b57cec5SDimitry Andric        if (!this->has_value())
9950b57cec5SDimitry Andric            __throw_bad_optional_access();
9960b57cec5SDimitry Andric        return this->__get();
9970b57cec5SDimitry Andric    }
9980b57cec5SDimitry Andric
9990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10000b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10010b57cec5SDimitry Andric    constexpr value_type& value() &
10020b57cec5SDimitry Andric    {
10030b57cec5SDimitry Andric        if (!this->has_value())
10040b57cec5SDimitry Andric            __throw_bad_optional_access();
10050b57cec5SDimitry Andric        return this->__get();
10060b57cec5SDimitry Andric    }
10070b57cec5SDimitry Andric
10080b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10090b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10100b57cec5SDimitry Andric    constexpr value_type&& value() &&
10110b57cec5SDimitry Andric    {
10120b57cec5SDimitry Andric        if (!this->has_value())
10130b57cec5SDimitry Andric            __throw_bad_optional_access();
10140b57cec5SDimitry Andric        return _VSTD::move(this->__get());
10150b57cec5SDimitry Andric    }
10160b57cec5SDimitry Andric
10170b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10180b57cec5SDimitry Andric    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10190b57cec5SDimitry Andric    constexpr value_type const&& value() const&&
10200b57cec5SDimitry Andric    {
10210b57cec5SDimitry Andric        if (!this->has_value())
10220b57cec5SDimitry Andric            __throw_bad_optional_access();
10230b57cec5SDimitry Andric        return _VSTD::move(this->__get());
10240b57cec5SDimitry Andric    }
10250b57cec5SDimitry Andric
10260b57cec5SDimitry Andric    template <class _Up>
10270b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10280b57cec5SDimitry Andric    constexpr value_type value_or(_Up&& __v) const&
10290b57cec5SDimitry Andric    {
10300b57cec5SDimitry Andric        static_assert(is_copy_constructible_v<value_type>,
10310b57cec5SDimitry Andric                      "optional<T>::value_or: T must be copy constructible");
10320b57cec5SDimitry Andric        static_assert(is_convertible_v<_Up, value_type>,
10330b57cec5SDimitry Andric                      "optional<T>::value_or: U must be convertible to T");
10340b57cec5SDimitry Andric        return this->has_value() ? this->__get() :
10350b57cec5SDimitry Andric                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
10360b57cec5SDimitry Andric    }
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andric    template <class _Up>
10390b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
10400b57cec5SDimitry Andric    constexpr value_type value_or(_Up&& __v) &&
10410b57cec5SDimitry Andric    {
10420b57cec5SDimitry Andric        static_assert(is_move_constructible_v<value_type>,
10430b57cec5SDimitry Andric                      "optional<T>::value_or: T must be move constructible");
10440b57cec5SDimitry Andric        static_assert(is_convertible_v<_Up, value_type>,
10450b57cec5SDimitry Andric                      "optional<T>::value_or: U must be convertible to T");
10460b57cec5SDimitry Andric        return this->has_value() ? _VSTD::move(this->__get()) :
10470b57cec5SDimitry Andric                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
10480b57cec5SDimitry Andric    }
10490b57cec5SDimitry Andric
10500eae32dcSDimitry Andric#if _LIBCPP_STD_VER > 20
10510eae32dcSDimitry Andric  template<class _Func>
105281ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10530eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) & {
10540eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&>;
10550eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
10560eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
10570eae32dcSDimitry Andric    if (*this)
10580eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
10590eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
10600eae32dcSDimitry Andric  }
10610eae32dcSDimitry Andric
10620eae32dcSDimitry Andric  template<class _Func>
106381ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10640eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) const& {
10650eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&>;
10660eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
10670eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
10680eae32dcSDimitry Andric    if (*this)
10690eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
10700eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
10710eae32dcSDimitry Andric  }
10720eae32dcSDimitry Andric
10730eae32dcSDimitry Andric  template<class _Func>
107481ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10750eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) && {
10760eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&&>;
10770eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
10780eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
10790eae32dcSDimitry Andric    if (*this)
10800eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
10810eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
10820eae32dcSDimitry Andric  }
10830eae32dcSDimitry Andric
10840eae32dcSDimitry Andric  template<class _Func>
10850eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
10860eae32dcSDimitry Andric  constexpr auto and_then(_Func&& __f) const&& {
10870eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&&>;
10880eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
10890eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
10900eae32dcSDimitry Andric    if (*this)
10910eae32dcSDimitry Andric      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
10920eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
10930eae32dcSDimitry Andric  }
10940eae32dcSDimitry Andric
10950eae32dcSDimitry Andric  template<class _Func>
109681ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
10970eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) & {
10980eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
10990eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
11000eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11010eae32dcSDimitry Andric                  "Result of f(value()) should not be std::in_place_t");
11020eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11030eae32dcSDimitry Andric                  "Result of f(value()) should not be std::nullopt_t");
11040eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
11050eae32dcSDimitry Andric    if (*this)
11060eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
11070eae32dcSDimitry Andric    return optional<_Up>();
11080eae32dcSDimitry Andric  }
11090eae32dcSDimitry Andric
11100eae32dcSDimitry Andric  template<class _Func>
111181ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11120eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) const& {
11130eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
11140eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
11150eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11160eae32dcSDimitry Andric                  "Result of f(value()) should not be std::in_place_t");
11170eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11180eae32dcSDimitry Andric                  "Result of f(value()) should not be std::nullopt_t");
11190eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
11200eae32dcSDimitry Andric    if (*this)
11210eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
11220eae32dcSDimitry Andric    return optional<_Up>();
11230eae32dcSDimitry Andric  }
11240eae32dcSDimitry Andric
11250eae32dcSDimitry Andric  template<class _Func>
112681ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11270eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) && {
11280eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
11290eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
11300eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11310eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::in_place_t");
11320eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11330eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::nullopt_t");
11340eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
11350eae32dcSDimitry Andric    if (*this)
11360eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
11370eae32dcSDimitry Andric    return optional<_Up>();
11380eae32dcSDimitry Andric  }
11390eae32dcSDimitry Andric
11400eae32dcSDimitry Andric  template<class _Func>
114181ad6265SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
11420eae32dcSDimitry Andric  constexpr auto transform(_Func&& __f) const&& {
11430eae32dcSDimitry Andric    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
11440eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
11450eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>,
11460eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::in_place_t");
11470eae32dcSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>,
11480eae32dcSDimitry Andric                  "Result of f(std::move(value())) should not be std::nullopt_t");
11490eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
11500eae32dcSDimitry Andric    if (*this)
11510eae32dcSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
11520eae32dcSDimitry Andric    return optional<_Up>();
11530eae32dcSDimitry Andric  }
11540eae32dcSDimitry Andric
11550eae32dcSDimitry Andric  template<invocable _Func>
11560eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
11570eae32dcSDimitry Andric  constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
11580eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
11590eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
11600eae32dcSDimitry Andric    if (*this)
11610eae32dcSDimitry Andric      return *this;
11620eae32dcSDimitry Andric    return _VSTD::forward<_Func>(__f)();
11630eae32dcSDimitry Andric  }
11640eae32dcSDimitry Andric
11650eae32dcSDimitry Andric  template<invocable _Func>
11660eae32dcSDimitry Andric  _LIBCPP_HIDE_FROM_ABI
11670eae32dcSDimitry Andric  constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
11680eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
11690eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
11700eae32dcSDimitry Andric    if (*this)
11710eae32dcSDimitry Andric      return _VSTD::move(*this);
11720eae32dcSDimitry Andric    return _VSTD::forward<_Func>(__f)();
11730eae32dcSDimitry Andric  }
11740eae32dcSDimitry Andric#endif // _LIBCPP_STD_VER > 20
11750eae32dcSDimitry Andric
11760b57cec5SDimitry Andric    using __base::reset;
11770b57cec5SDimitry Andric};
11780b57cec5SDimitry Andric
1179349cc55cSDimitry Andric#if _LIBCPP_STD_VER >= 17
118004eeddc0SDimitry Andrictemplate<class _Tp>
118104eeddc0SDimitry Andric    optional(_Tp) -> optional<_Tp>;
11820b57cec5SDimitry Andric#endif
11830b57cec5SDimitry Andric
11840b57cec5SDimitry Andric// Comparisons between optionals
11850b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
11860b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1187349cc55cSDimitry Andricenable_if_t<
1188*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() ==
1189*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
11900b57cec5SDimitry Andric    bool
11910b57cec5SDimitry Andric>
11920b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y)
11930b57cec5SDimitry Andric{
11940b57cec5SDimitry Andric    if (static_cast<bool>(__x) != static_cast<bool>(__y))
11950b57cec5SDimitry Andric        return false;
11960b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
11970b57cec5SDimitry Andric        return true;
11980b57cec5SDimitry Andric    return *__x == *__y;
11990b57cec5SDimitry Andric}
12000b57cec5SDimitry Andric
12010b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12020b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1203349cc55cSDimitry Andricenable_if_t<
1204*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() !=
1205*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
12060b57cec5SDimitry Andric    bool
12070b57cec5SDimitry Andric>
12080b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
12090b57cec5SDimitry Andric{
12100b57cec5SDimitry Andric    if (static_cast<bool>(__x) != static_cast<bool>(__y))
12110b57cec5SDimitry Andric        return true;
12120b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
12130b57cec5SDimitry Andric        return false;
12140b57cec5SDimitry Andric    return *__x != *__y;
12150b57cec5SDimitry Andric}
12160b57cec5SDimitry Andric
12170b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12180b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1219349cc55cSDimitry Andricenable_if_t<
1220*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <
1221*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
12220b57cec5SDimitry Andric    bool
12230b57cec5SDimitry Andric>
12240b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y)
12250b57cec5SDimitry Andric{
12260b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
12270b57cec5SDimitry Andric        return false;
12280b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
12290b57cec5SDimitry Andric        return true;
12300b57cec5SDimitry Andric    return *__x < *__y;
12310b57cec5SDimitry Andric}
12320b57cec5SDimitry Andric
12330b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12340b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1235349cc55cSDimitry Andricenable_if_t<
1236*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >
1237*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
12380b57cec5SDimitry Andric    bool
12390b57cec5SDimitry Andric>
12400b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y)
12410b57cec5SDimitry Andric{
12420b57cec5SDimitry Andric    if (!static_cast<bool>(__x))
12430b57cec5SDimitry Andric        return false;
12440b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
12450b57cec5SDimitry Andric        return true;
12460b57cec5SDimitry Andric    return *__x > *__y;
12470b57cec5SDimitry Andric}
12480b57cec5SDimitry Andric
12490b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12500b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1251349cc55cSDimitry Andricenable_if_t<
1252*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <=
1253*bdd1243dSDimitry 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))
12590b57cec5SDimitry Andric        return true;
12600b57cec5SDimitry Andric    if (!static_cast<bool>(__y))
12610b57cec5SDimitry Andric        return false;
12620b57cec5SDimitry Andric    return *__x <= *__y;
12630b57cec5SDimitry Andric}
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
12660b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1267349cc55cSDimitry Andricenable_if_t<
1268*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >=
1269*bdd1243dSDimitry 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>(__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 Andric// Comparisons with nullopt
12820b57cec5SDimitry Andrictemplate <class _Tp>
12830b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
12840b57cec5SDimitry Andricbool
12850b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, nullopt_t) noexcept
12860b57cec5SDimitry Andric{
12870b57cec5SDimitry Andric    return !static_cast<bool>(__x);
12880b57cec5SDimitry Andric}
12890b57cec5SDimitry Andric
12900b57cec5SDimitry Andrictemplate <class _Tp>
12910b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
12920b57cec5SDimitry Andricbool
12930b57cec5SDimitry Andricoperator==(nullopt_t, const optional<_Tp>& __x) noexcept
12940b57cec5SDimitry Andric{
12950b57cec5SDimitry Andric    return !static_cast<bool>(__x);
12960b57cec5SDimitry Andric}
12970b57cec5SDimitry Andric
12980b57cec5SDimitry Andrictemplate <class _Tp>
12990b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13000b57cec5SDimitry Andricbool
13010b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept
13020b57cec5SDimitry Andric{
13030b57cec5SDimitry Andric    return static_cast<bool>(__x);
13040b57cec5SDimitry Andric}
13050b57cec5SDimitry Andric
13060b57cec5SDimitry Andrictemplate <class _Tp>
13070b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13080b57cec5SDimitry Andricbool
13090b57cec5SDimitry Andricoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept
13100b57cec5SDimitry Andric{
13110b57cec5SDimitry Andric    return static_cast<bool>(__x);
13120b57cec5SDimitry Andric}
13130b57cec5SDimitry Andric
13140b57cec5SDimitry Andrictemplate <class _Tp>
13150b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13160b57cec5SDimitry Andricbool
13170b57cec5SDimitry Andricoperator<(const optional<_Tp>&, nullopt_t) noexcept
13180b57cec5SDimitry Andric{
13190b57cec5SDimitry Andric    return false;
13200b57cec5SDimitry Andric}
13210b57cec5SDimitry Andric
13220b57cec5SDimitry Andrictemplate <class _Tp>
13230b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13240b57cec5SDimitry Andricbool
13250b57cec5SDimitry Andricoperator<(nullopt_t, const optional<_Tp>& __x) noexcept
13260b57cec5SDimitry Andric{
13270b57cec5SDimitry Andric    return static_cast<bool>(__x);
13280b57cec5SDimitry Andric}
13290b57cec5SDimitry Andric
13300b57cec5SDimitry Andrictemplate <class _Tp>
13310b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13320b57cec5SDimitry Andricbool
13330b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept
13340b57cec5SDimitry Andric{
13350b57cec5SDimitry Andric    return !static_cast<bool>(__x);
13360b57cec5SDimitry Andric}
13370b57cec5SDimitry Andric
13380b57cec5SDimitry Andrictemplate <class _Tp>
13390b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13400b57cec5SDimitry Andricbool
13410b57cec5SDimitry Andricoperator<=(nullopt_t, const optional<_Tp>&) noexcept
13420b57cec5SDimitry Andric{
13430b57cec5SDimitry Andric    return true;
13440b57cec5SDimitry Andric}
13450b57cec5SDimitry Andric
13460b57cec5SDimitry Andrictemplate <class _Tp>
13470b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13480b57cec5SDimitry Andricbool
13490b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, nullopt_t) noexcept
13500b57cec5SDimitry Andric{
13510b57cec5SDimitry Andric    return static_cast<bool>(__x);
13520b57cec5SDimitry Andric}
13530b57cec5SDimitry Andric
13540b57cec5SDimitry Andrictemplate <class _Tp>
13550b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13560b57cec5SDimitry Andricbool
13570b57cec5SDimitry Andricoperator>(nullopt_t, const optional<_Tp>&) noexcept
13580b57cec5SDimitry Andric{
13590b57cec5SDimitry Andric    return false;
13600b57cec5SDimitry Andric}
13610b57cec5SDimitry Andric
13620b57cec5SDimitry Andrictemplate <class _Tp>
13630b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13640b57cec5SDimitry Andricbool
13650b57cec5SDimitry Andricoperator>=(const optional<_Tp>&, nullopt_t) noexcept
13660b57cec5SDimitry Andric{
13670b57cec5SDimitry Andric    return true;
13680b57cec5SDimitry Andric}
13690b57cec5SDimitry Andric
13700b57cec5SDimitry Andrictemplate <class _Tp>
13710b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
13720b57cec5SDimitry Andricbool
13730b57cec5SDimitry Andricoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept
13740b57cec5SDimitry Andric{
13750b57cec5SDimitry Andric    return !static_cast<bool>(__x);
13760b57cec5SDimitry Andric}
13770b57cec5SDimitry Andric
13780b57cec5SDimitry Andric// Comparisons with T
13790b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
13800b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1381349cc55cSDimitry Andricenable_if_t<
1382*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() ==
1383*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
13840b57cec5SDimitry Andric    bool
13850b57cec5SDimitry Andric>
13860b57cec5SDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v)
13870b57cec5SDimitry Andric{
13880b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x == __v : false;
13890b57cec5SDimitry Andric}
13900b57cec5SDimitry Andric
13910b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
13920b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1393349cc55cSDimitry Andricenable_if_t<
1394*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() ==
1395*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
13960b57cec5SDimitry Andric    bool
13970b57cec5SDimitry Andric>
13980b57cec5SDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x)
13990b57cec5SDimitry Andric{
14000b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v == *__x : false;
14010b57cec5SDimitry Andric}
14020b57cec5SDimitry Andric
14030b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14040b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1405349cc55cSDimitry Andricenable_if_t<
1406*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() !=
1407*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14080b57cec5SDimitry Andric    bool
14090b57cec5SDimitry Andric>
14100b57cec5SDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v)
14110b57cec5SDimitry Andric{
14120b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x != __v : true;
14130b57cec5SDimitry Andric}
14140b57cec5SDimitry Andric
14150b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14160b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1417349cc55cSDimitry Andricenable_if_t<
1418*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() !=
1419*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14200b57cec5SDimitry Andric    bool
14210b57cec5SDimitry Andric>
14220b57cec5SDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x)
14230b57cec5SDimitry Andric{
14240b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v != *__x : true;
14250b57cec5SDimitry Andric}
14260b57cec5SDimitry Andric
14270b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14280b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1429349cc55cSDimitry Andricenable_if_t<
1430*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <
1431*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14320b57cec5SDimitry Andric    bool
14330b57cec5SDimitry Andric>
14340b57cec5SDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v)
14350b57cec5SDimitry Andric{
14360b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x < __v : true;
14370b57cec5SDimitry Andric}
14380b57cec5SDimitry Andric
14390b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14400b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1441349cc55cSDimitry Andricenable_if_t<
1442*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <
1443*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14440b57cec5SDimitry Andric    bool
14450b57cec5SDimitry Andric>
14460b57cec5SDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x)
14470b57cec5SDimitry Andric{
14480b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v < *__x : false;
14490b57cec5SDimitry Andric}
14500b57cec5SDimitry Andric
14510b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14520b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1453349cc55cSDimitry Andricenable_if_t<
1454*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <=
1455*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14560b57cec5SDimitry Andric    bool
14570b57cec5SDimitry Andric>
14580b57cec5SDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v)
14590b57cec5SDimitry Andric{
14600b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x <= __v : true;
14610b57cec5SDimitry Andric}
14620b57cec5SDimitry Andric
14630b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14640b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1465349cc55cSDimitry Andricenable_if_t<
1466*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <=
1467*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14680b57cec5SDimitry Andric    bool
14690b57cec5SDimitry Andric>
14700b57cec5SDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x)
14710b57cec5SDimitry Andric{
14720b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v <= *__x : false;
14730b57cec5SDimitry Andric}
14740b57cec5SDimitry Andric
14750b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14760b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1477349cc55cSDimitry Andricenable_if_t<
1478*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >
1479*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14800b57cec5SDimitry Andric    bool
14810b57cec5SDimitry Andric>
14820b57cec5SDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v)
14830b57cec5SDimitry Andric{
14840b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x > __v : false;
14850b57cec5SDimitry Andric}
14860b57cec5SDimitry Andric
14870b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
14880b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1489349cc55cSDimitry Andricenable_if_t<
1490*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >
1491*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
14920b57cec5SDimitry Andric    bool
14930b57cec5SDimitry Andric>
14940b57cec5SDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x)
14950b57cec5SDimitry Andric{
14960b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v > *__x : true;
14970b57cec5SDimitry Andric}
14980b57cec5SDimitry Andric
14990b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15000b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1501349cc55cSDimitry Andricenable_if_t<
1502*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >=
1503*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15040b57cec5SDimitry Andric    bool
15050b57cec5SDimitry Andric>
15060b57cec5SDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v)
15070b57cec5SDimitry Andric{
15080b57cec5SDimitry Andric    return static_cast<bool>(__x) ? *__x >= __v : false;
15090b57cec5SDimitry Andric}
15100b57cec5SDimitry Andric
15110b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
15120b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
1513349cc55cSDimitry Andricenable_if_t<
1514*bdd1243dSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >=
1515*bdd1243dSDimitry Andric        std::declval<const _Up&>()), bool>,
15160b57cec5SDimitry Andric    bool
15170b57cec5SDimitry Andric>
15180b57cec5SDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x)
15190b57cec5SDimitry Andric{
15200b57cec5SDimitry Andric    return static_cast<bool>(__x) ? __v >= *__x : true;
15210b57cec5SDimitry Andric}
15220b57cec5SDimitry Andric
15230b57cec5SDimitry Andric
15240b57cec5SDimitry Andrictemplate <class _Tp>
1525*bdd1243dSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
1526349cc55cSDimitry Andricenable_if_t<
15270b57cec5SDimitry Andric    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
15280b57cec5SDimitry Andric    void
15290b57cec5SDimitry Andric>
15300b57cec5SDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
15310b57cec5SDimitry Andric{
15320b57cec5SDimitry Andric    __x.swap(__y);
15330b57cec5SDimitry Andric}
15340b57cec5SDimitry Andric
15350b57cec5SDimitry Andrictemplate <class _Tp>
15360b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
15370b57cec5SDimitry Andricoptional<decay_t<_Tp>> make_optional(_Tp&& __v)
15380b57cec5SDimitry Andric{
15390b57cec5SDimitry Andric    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
15400b57cec5SDimitry Andric}
15410b57cec5SDimitry Andric
15420b57cec5SDimitry Andrictemplate <class _Tp, class... _Args>
15430b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
15440b57cec5SDimitry Andricoptional<_Tp> make_optional(_Args&&... __args)
15450b57cec5SDimitry Andric{
15460b57cec5SDimitry Andric    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
15470b57cec5SDimitry Andric}
15480b57cec5SDimitry Andric
15490b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args>
15500b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
15510b57cec5SDimitry Andricoptional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
15520b57cec5SDimitry Andric{
15530b57cec5SDimitry Andric    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
15540b57cec5SDimitry Andric}
15550b57cec5SDimitry Andric
15560b57cec5SDimitry Andrictemplate <class _Tp>
15570b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<
15580b57cec5SDimitry Andric    __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
15590b57cec5SDimitry Andric>
15600b57cec5SDimitry Andric{
1561fe6060f1SDimitry Andric#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1562fe6060f1SDimitry Andric    _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1563fe6060f1SDimitry Andric    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t        result_type;
1564fe6060f1SDimitry Andric#endif
15650b57cec5SDimitry Andric
15660b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
1567fe6060f1SDimitry Andric    size_t operator()(const optional<_Tp>& __opt) const
15680b57cec5SDimitry Andric    {
15690b57cec5SDimitry Andric        return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
15700b57cec5SDimitry Andric    }
15710b57cec5SDimitry Andric};
15720b57cec5SDimitry Andric
15730b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
15740b57cec5SDimitry Andric
15750b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 14
15760b57cec5SDimitry Andric
1577*bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
1578*bdd1243dSDimitry Andric#  include <atomic>
1579*bdd1243dSDimitry Andric#  include <climits>
1580*bdd1243dSDimitry Andric#  include <concepts>
1581*bdd1243dSDimitry Andric#  include <ctime>
1582*bdd1243dSDimitry Andric#  include <iterator>
1583*bdd1243dSDimitry Andric#  include <memory>
1584*bdd1243dSDimitry Andric#  include <ratio>
1585*bdd1243dSDimitry Andric#  include <tuple>
1586*bdd1243dSDimitry Andric#  include <typeinfo>
1587*bdd1243dSDimitry Andric#  include <utility>
1588*bdd1243dSDimitry Andric#  include <variant>
1589*bdd1243dSDimitry Andric#endif
1590*bdd1243dSDimitry Andric
15910b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL
1592