xref: /freebsd/contrib/llvm-project/libcxx/include/optional (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_OPTIONAL
110b57cec5SDimitry Andric#define _LIBCPP_OPTIONAL
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    optional synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric// C++1z
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricnamespace std {
1906c3fb27SDimitry Andric  // [optional.optional], class template optional
2006c3fb27SDimitry Andric  template <class T>
2106c3fb27SDimitry Andric    class optional;
220b57cec5SDimitry Andric
2306c3fb27SDimitry Andric  template<class T>
2406c3fb27SDimitry Andric    concept is-derived-from-optional = requires(const T& t) {       // exposition only
2506c3fb27SDimitry Andric      []<class U>(const optional<U>&){ }(t);
2606c3fb27SDimitry Andric    };
2706c3fb27SDimitry Andric
2806c3fb27SDimitry Andric  // [optional.nullopt], no-value state indicator
290b57cec5SDimitry Andric  struct nullopt_t{see below };
300b57cec5SDimitry Andric  inline constexpr nullopt_t nullopt(unspecified );
310b57cec5SDimitry Andric
3206c3fb27SDimitry Andric  // [optional.bad.access], class bad_optional_access
330b57cec5SDimitry Andric  class bad_optional_access;
340b57cec5SDimitry Andric
3506c3fb27SDimitry Andric  // [optional.relops], relational operators
360b57cec5SDimitry Andric  template <class T, class U>
370b57cec5SDimitry Andric    constexpr bool operator==(const optional<T>&, const optional<U>&);
380b57cec5SDimitry Andric  template <class T, class U>
390b57cec5SDimitry Andric    constexpr bool operator!=(const optional<T>&, const optional<U>&);
400b57cec5SDimitry Andric  template <class T, class U>
410b57cec5SDimitry Andric    constexpr bool operator<(const optional<T>&, const optional<U>&);
420b57cec5SDimitry Andric  template <class T, class U>
430b57cec5SDimitry Andric    constexpr bool operator>(const optional<T>&, const optional<U>&);
440b57cec5SDimitry Andric  template <class T, class U>
450b57cec5SDimitry Andric    constexpr bool operator<=(const optional<T>&, const optional<U>&);
460b57cec5SDimitry Andric  template <class T, class U>
470b57cec5SDimitry Andric    constexpr bool operator>=(const optional<T>&, const optional<U>&);
4806c3fb27SDimitry Andric  template<class T, three_way_comparable_with<T> U>
4906c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
5006c3fb27SDimitry Andric      operator<=>(const optional<T>&, const optional<U>&); // since C++20
510b57cec5SDimitry Andric
5206c3fb27SDimitry Andric  // [optional.nullops], comparison with nullopt
530b57cec5SDimitry Andric  template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
5406c3fb27SDimitry Andric  template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17
5506c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17
5606c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17
5706c3fb27SDimitry Andric  template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;  // until C++17
5806c3fb27SDimitry Andric  template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;  // until C++17
5906c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17
6006c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17
6106c3fb27SDimitry Andric  template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;  // until C++17
6206c3fb27SDimitry Andric  template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;  // until C++17
6306c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17
6406c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17
6506c3fb27SDimitry Andric  template<class T>
6606c3fb27SDimitry Andric    constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept;     // since C++20
670b57cec5SDimitry Andric
6806c3fb27SDimitry Andric  // [optional.comp.with.t], comparison with T
690b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator==(const optional<T>&, const U&);
700b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator==(const T&, const optional<U>&);
710b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
720b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
730b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<(const optional<T>&, const U&);
740b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<(const T&, const optional<U>&);
750b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
760b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
770b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>(const optional<T>&, const U&);
780b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>(const T&, const optional<U>&);
790b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
800b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
8106c3fb27SDimitry Andric  template<class T, class U>
8206c3fb27SDimitry Andric      requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U>
8306c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
8406c3fb27SDimitry Andric      operator<=>(const optional<T>&, const U&);                                       // since C++20
850b57cec5SDimitry Andric
8606c3fb27SDimitry Andric  // [optional.specalg], specialized algorithms
8706c3fb27SDimitry Andric  template<class T>
8806c3fb27SDimitry Andric    void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
8906c3fb27SDimitry Andric
9006c3fb27SDimitry Andric  template<class T>
9106c3fb27SDimitry Andric    constexpr optional<see below > make_optional(T&&);
920b57cec5SDimitry Andric  template<class T, class... Args>
930b57cec5SDimitry Andric    constexpr optional<T> make_optional(Args&&... args);
940b57cec5SDimitry Andric  template<class T, class U, class... Args>
950b57cec5SDimitry Andric    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
960b57cec5SDimitry Andric
9706c3fb27SDimitry Andric  // [optional.hash], hash support
980b57cec5SDimitry Andric  template<class T> struct hash;
990b57cec5SDimitry Andric  template<class T> struct hash<optional<T>>;
1000b57cec5SDimitry Andric
10106c3fb27SDimitry Andric  template<class T>
10206c3fb27SDimitry Andric  class optional {
1030b57cec5SDimitry Andric  public:
1040b57cec5SDimitry Andric    using value_type = T;
1050b57cec5SDimitry Andric
10606c3fb27SDimitry Andric    // [optional.ctor], constructors
1070b57cec5SDimitry Andric    constexpr optional() noexcept;
1080b57cec5SDimitry Andric    constexpr optional(nullopt_t) noexcept;
109bdd1243dSDimitry Andric    constexpr optional(const optional &);
110bdd1243dSDimitry Andric    constexpr optional(optional &&) noexcept(see below);
11106c3fb27SDimitry Andric    template<class... Args>
11206c3fb27SDimitry Andric      constexpr explicit optional(in_place_t, Args &&...);
1130b57cec5SDimitry Andric    template<class U, class... Args>
1140b57cec5SDimitry Andric      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
1150b57cec5SDimitry Andric    template<class U = T>
11681ad6265SDimitry Andric      constexpr explicit(see-below) optional(U &&);
1170b57cec5SDimitry Andric    template<class U>
11881ad6265SDimitry Andric      explicit(see-below) optional(const optional<U> &);                          // constexpr in C++20
1190b57cec5SDimitry Andric    template<class U>
12081ad6265SDimitry Andric      explicit(see-below) optional(optional<U> &&);                               // constexpr in C++20
1210b57cec5SDimitry Andric
12206c3fb27SDimitry Andric    // [optional.dtor], destructor
123fe6060f1SDimitry Andric    ~optional(); // constexpr in C++20
1240b57cec5SDimitry Andric
12506c3fb27SDimitry Andric    // [optional.assign], assignment
126fe6060f1SDimitry Andric    optional &operator=(nullopt_t) noexcept;                                      // constexpr in C++20
127bdd1243dSDimitry Andric    constexpr optional &operator=(const optional &);
128bdd1243dSDimitry Andric    constexpr optional &operator=(optional &&) noexcept(see below);
129fe6060f1SDimitry Andric    template<class U = T> optional &operator=(U &&);                              // constexpr in C++20
130fe6060f1SDimitry Andric    template<class U> optional &operator=(const optional<U> &);                   // constexpr in C++20
131fe6060f1SDimitry Andric    template<class U> optional &operator=(optional<U> &&);                        // constexpr in C++20
132fe6060f1SDimitry Andric    template<class... Args> T& emplace(Args &&...);                               // constexpr in C++20
13306c3fb27SDimitry Andric    template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
1340b57cec5SDimitry Andric
13506c3fb27SDimitry Andric    // [optional.swap], swap
136fe6060f1SDimitry Andric    void swap(optional &) noexcept(see below ); // constexpr in C++20
1370b57cec5SDimitry Andric
13806c3fb27SDimitry Andric    // [optional.observe], observers
1390fca6ea1SDimitry Andric    constexpr T const *operator->() const noexcept;
1400fca6ea1SDimitry Andric    constexpr T *operator->() noexcept;
1410fca6ea1SDimitry Andric    constexpr T const &operator*() const & noexcept;
1420fca6ea1SDimitry Andric    constexpr T &operator*() & noexcept;
1430fca6ea1SDimitry Andric    constexpr T &&operator*() && noexcept;
1440fca6ea1SDimitry Andric    constexpr const T &&operator*() const && noexcept;
1450b57cec5SDimitry Andric    constexpr explicit operator bool() const noexcept;
1460b57cec5SDimitry Andric    constexpr bool has_value() const noexcept;
1470b57cec5SDimitry Andric    constexpr T const &value() const &;
1480b57cec5SDimitry Andric    constexpr T &value() &;
1490b57cec5SDimitry Andric    constexpr T &&value() &&;
1500b57cec5SDimitry Andric    constexpr const T &&value() const &&;
1510b57cec5SDimitry Andric    template<class U> constexpr T value_or(U &&) const &;
1520b57cec5SDimitry Andric    template<class U> constexpr T value_or(U &&) &&;
1530b57cec5SDimitry Andric
1540eae32dcSDimitry Andric    // [optional.monadic], monadic operations
1550eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &;         // since C++23
1560eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &&;        // since C++23
1570eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&;    // since C++23
1580eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&&;   // since C++23
1590eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &;        // since C++23
1600eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &&;       // since C++23
1610eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&;   // since C++23
1620eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&&;  // since C++23
1630eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) &&;     // since C++23
1640eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) const&; // since C++23
1650eae32dcSDimitry Andric
16606c3fb27SDimitry Andric    // [optional.mod], modifiers
167fe6060f1SDimitry Andric    void reset() noexcept;                                      // constexpr in C++20
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric  private:
1700b57cec5SDimitry Andric    T *val;         // exposition only
1710b57cec5SDimitry Andric  };
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric  template<class T>
1740b57cec5SDimitry Andric    optional(T) -> optional<T>;
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric} // namespace std
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric*/
1790b57cec5SDimitry Andric
1800fca6ea1SDimitry Andric#include <__assert>
18106c3fb27SDimitry Andric#include <__compare/compare_three_way_result.h>
18206c3fb27SDimitry Andric#include <__compare/three_way_comparable.h>
1830eae32dcSDimitry Andric#include <__concepts/invocable.h>
184fe6060f1SDimitry Andric#include <__config>
1855f757f3fSDimitry Andric#include <__exception/exception.h>
18681ad6265SDimitry Andric#include <__functional/hash.h>
18781ad6265SDimitry Andric#include <__functional/invoke.h>
18881ad6265SDimitry Andric#include <__functional/unary_function.h>
1890fca6ea1SDimitry Andric#include <__fwd/functional.h>
19006c3fb27SDimitry Andric#include <__memory/addressof.h>
19181ad6265SDimitry Andric#include <__memory/construct_at.h>
19206c3fb27SDimitry Andric#include <__tuple/sfinae_helpers.h>
19306c3fb27SDimitry Andric#include <__type_traits/add_pointer.h>
19406c3fb27SDimitry Andric#include <__type_traits/conditional.h>
19506c3fb27SDimitry Andric#include <__type_traits/conjunction.h>
19606c3fb27SDimitry Andric#include <__type_traits/decay.h>
19706c3fb27SDimitry Andric#include <__type_traits/disjunction.h>
19806c3fb27SDimitry Andric#include <__type_traits/is_array.h>
19906c3fb27SDimitry Andric#include <__type_traits/is_assignable.h>
20006c3fb27SDimitry Andric#include <__type_traits/is_constructible.h>
20106c3fb27SDimitry Andric#include <__type_traits/is_convertible.h>
20206c3fb27SDimitry Andric#include <__type_traits/is_destructible.h>
2030fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_assignable.h>
2040fca6ea1SDimitry Andric#include <__type_traits/is_nothrow_constructible.h>
20506c3fb27SDimitry Andric#include <__type_traits/is_object.h>
20606c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
20706c3fb27SDimitry Andric#include <__type_traits/is_scalar.h>
20806c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
2090fca6ea1SDimitry Andric#include <__type_traits/is_trivially_assignable.h>
2100fca6ea1SDimitry Andric#include <__type_traits/is_trivially_constructible.h>
21106c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h>
2120fca6ea1SDimitry Andric#include <__type_traits/is_trivially_relocatable.h>
21306c3fb27SDimitry Andric#include <__type_traits/negation.h>
21406c3fb27SDimitry Andric#include <__type_traits/remove_const.h>
21506c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h>
21606c3fb27SDimitry Andric#include <__type_traits/remove_reference.h>
21706c3fb27SDimitry Andric#include <__utility/declval.h>
21881ad6265SDimitry Andric#include <__utility/forward.h>
21981ad6265SDimitry Andric#include <__utility/in_place.h>
22081ad6265SDimitry Andric#include <__utility/move.h>
22181ad6265SDimitry Andric#include <__utility/swap.h>
22206c3fb27SDimitry Andric#include <__verbose_abort>
2230b57cec5SDimitry Andric#include <initializer_list>
2240b57cec5SDimitry Andric#include <new>
2250b57cec5SDimitry Andric#include <version>
2260b57cec5SDimitry Andric
22781ad6265SDimitry Andric// standard-mandated includes
228bdd1243dSDimitry Andric
229bdd1243dSDimitry Andric// [optional.syn]
23081ad6265SDimitry Andric#include <compare>
23181ad6265SDimitry Andric
2320b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2330b57cec5SDimitry Andric#  pragma GCC system_header
2340b57cec5SDimitry Andric#endif
2350b57cec5SDimitry Andric
23606c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS
23706c3fb27SDimitry Andric#include <__undef_macros>
23806c3fb27SDimitry Andric
2390b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace
2400b57cec5SDimitry Andric{
2410b57cec5SDimitry Andric
242cb14a3feSDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public exception {
2430b57cec5SDimitry Andricpublic:
2445f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT                                      = default;
2455f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT            = default;
2465f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default;
2470b57cec5SDimitry Andric  // Get the key function ~bad_optional_access() into the dylib
248bdd1243dSDimitry Andric  ~bad_optional_access() _NOEXCEPT override;
249bdd1243dSDimitry Andric  const char* what() const _NOEXCEPT override;
2500b57cec5SDimitry Andric};
2510b57cec5SDimitry Andric
2520eae32dcSDimitry Andric} // namespace std
2530b57cec5SDimitry Andric
25406c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2570b57cec5SDimitry Andric
258cb14a3feSDimitry Andric_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS void
259cb14a3feSDimitry Andric__throw_bad_optional_access() {
26006c3fb27SDimitry Andric#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2610b57cec5SDimitry Andric  throw bad_optional_access();
2620b57cec5SDimitry Andric#  else
26306c3fb27SDimitry Andric  _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode");
2640b57cec5SDimitry Andric#  endif
2650b57cec5SDimitry Andric}
2660b57cec5SDimitry Andric
267cb14a3feSDimitry Andricstruct nullopt_t {
268cb14a3feSDimitry Andric  struct __secret_tag {
269cb14a3feSDimitry Andric    explicit __secret_tag() = default;
270cb14a3feSDimitry Andric  };
2715f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
2720b57cec5SDimitry Andric};
2730b57cec5SDimitry Andric
274349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
2750b57cec5SDimitry Andric
2760eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {};
2770eae32dcSDimitry Andric
2780b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
2790b57cec5SDimitry Andricstruct __optional_destruct_base;
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andrictemplate <class _Tp>
282cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, false> {
2830b57cec5SDimitry Andric  typedef _Tp value_type;
284cb14a3feSDimitry Andric  static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
285cb14a3feSDimitry Andric  union {
2860b57cec5SDimitry Andric    char __null_state_;
2870b57cec5SDimitry Andric    value_type __val_;
2880b57cec5SDimitry Andric  };
2890b57cec5SDimitry Andric  bool __engaged_;
2900b57cec5SDimitry Andric
291cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() {
2920b57cec5SDimitry Andric    if (__engaged_)
2930b57cec5SDimitry Andric      __val_.~value_type();
2940b57cec5SDimitry Andric  }
2950b57cec5SDimitry Andric
296cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
2970b57cec5SDimitry Andric
2980b57cec5SDimitry Andric  template <class... _Args>
299cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
300cb14a3feSDimitry Andric      : __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
3010b57cec5SDimitry Andric
30206c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
3030eae32dcSDimitry Andric  template <class _Fp, class... _Args>
304*62987288SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(
305cb14a3feSDimitry Andric      __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3065f757f3fSDimitry Andric      : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
3070eae32dcSDimitry Andric#  endif
3080eae32dcSDimitry Andric
309cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
310cb14a3feSDimitry Andric    if (__engaged_) {
3110b57cec5SDimitry Andric      __val_.~value_type();
3120b57cec5SDimitry Andric      __engaged_ = false;
3130b57cec5SDimitry Andric    }
3140b57cec5SDimitry Andric  }
3150b57cec5SDimitry Andric};
3160b57cec5SDimitry Andric
3170b57cec5SDimitry Andrictemplate <class _Tp>
318cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, true> {
3190b57cec5SDimitry Andric  typedef _Tp value_type;
320cb14a3feSDimitry Andric  static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
321cb14a3feSDimitry Andric  union {
3220b57cec5SDimitry Andric    char __null_state_;
3230b57cec5SDimitry Andric    value_type __val_;
3240b57cec5SDimitry Andric  };
3250b57cec5SDimitry Andric  bool __engaged_;
3260b57cec5SDimitry Andric
327cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric  template <class... _Args>
330cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
331cb14a3feSDimitry Andric      : __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
3320b57cec5SDimitry Andric
33306c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
3340eae32dcSDimitry Andric  template <class _Fp, class... _Args>
335cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(
336cb14a3feSDimitry Andric      __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3375f757f3fSDimitry Andric      : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
3380eae32dcSDimitry Andric#  endif
3390eae32dcSDimitry Andric
340cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
341cb14a3feSDimitry Andric    if (__engaged_) {
3420b57cec5SDimitry Andric      __engaged_ = false;
3430b57cec5SDimitry Andric    }
3440b57cec5SDimitry Andric  }
3450b57cec5SDimitry Andric};
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value>
348cb14a3feSDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> {
3490b57cec5SDimitry Andric  using __base     = __optional_destruct_base<_Tp>;
3500b57cec5SDimitry Andric  using value_type = _Tp;
3510b57cec5SDimitry Andric  using __base::__base;
3520b57cec5SDimitry Andric
353cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; }
3540b57cec5SDimitry Andric
355cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; }
356cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; }
357cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); }
358cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); }
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric  template <class... _Args>
361cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) {
36206c3fb27SDimitry Andric    _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
3635f757f3fSDimitry Andric    std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...);
3640b57cec5SDimitry Andric    this->__engaged_ = true;
3650b57cec5SDimitry Andric  }
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric  template <class _That>
368cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
3690b57cec5SDimitry Andric    if (__opt.has_value())
3705f757f3fSDimitry Andric      __construct(std::forward<_That>(__opt).__get());
3710b57cec5SDimitry Andric  }
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric  template <class _That>
374cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
375cb14a3feSDimitry Andric    if (this->__engaged_ == __opt.has_value()) {
3760b57cec5SDimitry Andric      if (this->__engaged_)
3775f757f3fSDimitry Andric        this->__val_ = std::forward<_That>(__opt).__get();
378cb14a3feSDimitry Andric    } else {
3790b57cec5SDimitry Andric      if (this->__engaged_)
3800b57cec5SDimitry Andric        this->reset();
3810b57cec5SDimitry Andric      else
3825f757f3fSDimitry Andric        __construct(std::forward<_That>(__opt).__get());
3830b57cec5SDimitry Andric    }
3840b57cec5SDimitry Andric  }
3850b57cec5SDimitry Andric};
3860b57cec5SDimitry Andric
38781ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may
38881ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented
38981ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner.
3900b57cec5SDimitry Andrictemplate <class _Tp>
391cb14a3feSDimitry Andricstruct __optional_storage_base<_Tp, true> {
3920b57cec5SDimitry Andric  using value_type = _Tp;
3930b57cec5SDimitry Andric  using __raw_type = remove_reference_t<_Tp>;
3940b57cec5SDimitry Andric  __raw_type* __value_;
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric  template <class _Up>
39706c3fb27SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
398bdd1243dSDimitry Andric    using _RawUp = __libcpp_remove_reference_t<_Up>;
3990b57cec5SDimitry Andric    using _UpPtr = _RawUp*;
400bdd1243dSDimitry Andric    using _RawTp = __libcpp_remove_reference_t<_Tp>;
4010b57cec5SDimitry Andric    using _TpPtr = _RawTp*;
402cb14a3feSDimitry Andric    using _CheckLValueArg =
403cb14a3feSDimitry Andric        integral_constant<bool,
404cb14a3feSDimitry Andric                          (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) ||
405cb14a3feSDimitry Andric                              is_same<_RawUp, reference_wrapper<_RawTp>>::value ||
406cb14a3feSDimitry Andric                              is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value >;
407cb14a3feSDimitry Andric    return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) ||
408cb14a3feSDimitry Andric           (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
4090b57cec5SDimitry Andric            is_convertible<_UpPtr, _TpPtr>::value);
4100b57cec5SDimitry Andric  }
4110b57cec5SDimitry Andric
412cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric  template <class _UArg>
415cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
416cb14a3feSDimitry Andric      : __value_(std::addressof(__uarg)) {
4170b57cec5SDimitry Andric    static_assert(__can_bind_reference<_UArg>(),
4180b57cec5SDimitry Andric                  "Attempted to construct a reference element in tuple from a "
4190b57cec5SDimitry Andric                  "possible temporary");
4200b57cec5SDimitry Andric  }
4210b57cec5SDimitry Andric
422cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
4230b57cec5SDimitry Andric
424cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; }
4250b57cec5SDimitry Andric
426cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; }
4270b57cec5SDimitry Andric
428cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); }
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric  template <class _UArg>
431cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) {
43206c3fb27SDimitry Andric    _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
4330b57cec5SDimitry Andric    static_assert(__can_bind_reference<_UArg>(),
4340b57cec5SDimitry Andric                  "Attempted to construct a reference element in tuple from a "
4350b57cec5SDimitry Andric                  "possible temporary");
4365f757f3fSDimitry Andric    __value_ = std::addressof(__val);
4370b57cec5SDimitry Andric  }
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric  template <class _That>
440cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
4410b57cec5SDimitry Andric    if (__opt.has_value())
4425f757f3fSDimitry Andric      __construct(std::forward<_That>(__opt).__get());
4430b57cec5SDimitry Andric  }
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric  template <class _That>
446cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
447cb14a3feSDimitry Andric    if (has_value() == __opt.has_value()) {
4480b57cec5SDimitry Andric      if (has_value())
4495f757f3fSDimitry Andric        *__value_ = std::forward<_That>(__opt).__get();
450cb14a3feSDimitry Andric    } else {
4510b57cec5SDimitry Andric      if (has_value())
4520b57cec5SDimitry Andric        reset();
4530b57cec5SDimitry Andric      else
4545f757f3fSDimitry Andric        __construct(std::forward<_That>(__opt).__get());
4550b57cec5SDimitry Andric    }
4560b57cec5SDimitry Andric  }
4570b57cec5SDimitry Andric};
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
460cb14a3feSDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> {
4610b57cec5SDimitry Andric  using __optional_storage_base<_Tp>::__optional_storage_base;
4620b57cec5SDimitry Andric};
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andrictemplate <class _Tp>
465cb14a3feSDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> {
4660b57cec5SDimitry Andric  using __optional_storage_base<_Tp>::__optional_storage_base;
4670b57cec5SDimitry Andric
468cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default;
4690b57cec5SDimitry Andric
470cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) {
4710b57cec5SDimitry Andric    this->__construct_from(__opt);
4720b57cec5SDimitry Andric  }
4730b57cec5SDimitry Andric
474cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&)                 = default;
475cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default;
476cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&)      = default;
4770b57cec5SDimitry Andric};
4780b57cec5SDimitry Andric
4790b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
480cb14a3feSDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> {
4810b57cec5SDimitry Andric  using __optional_copy_base<_Tp>::__optional_copy_base;
4820b57cec5SDimitry Andric};
4830b57cec5SDimitry Andric
4840b57cec5SDimitry Andrictemplate <class _Tp>
485cb14a3feSDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> {
4860b57cec5SDimitry Andric  using value_type = _Tp;
4870b57cec5SDimitry Andric  using __optional_copy_base<_Tp>::__optional_copy_base;
4880b57cec5SDimitry Andric
489cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base()                            = default;
490cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default;
4910b57cec5SDimitry Andric
492cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
493cb14a3feSDimitry Andric  __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) {
4945f757f3fSDimitry Andric    this->__construct_from(std::move(__opt));
4950b57cec5SDimitry Andric  }
4960b57cec5SDimitry Andric
497cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default;
498cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&)      = default;
4990b57cec5SDimitry Andric};
5000b57cec5SDimitry Andric
501cb14a3feSDimitry Andrictemplate <class _Tp,
502cb14a3feSDimitry Andric          bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value &&
5030b57cec5SDimitry Andric                 is_trivially_copy_assignable<_Tp>::value>
504cb14a3feSDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> {
5050b57cec5SDimitry Andric  using __optional_move_base<_Tp>::__optional_move_base;
5060b57cec5SDimitry Andric};
5070b57cec5SDimitry Andric
5080b57cec5SDimitry Andrictemplate <class _Tp>
509cb14a3feSDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> {
5100b57cec5SDimitry Andric  using __optional_move_base<_Tp>::__optional_move_base;
5110b57cec5SDimitry Andric
512cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base()                                   = default;
513cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
514cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&)      = default;
5150b57cec5SDimitry Andric
516cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base&
517cb14a3feSDimitry Andric  operator=(const __optional_copy_assign_base& __opt) {
5180b57cec5SDimitry Andric    this->__assign_from(__opt);
5190b57cec5SDimitry Andric    return *this;
5200b57cec5SDimitry Andric  }
5210b57cec5SDimitry Andric
522cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
5230b57cec5SDimitry Andric};
5240b57cec5SDimitry Andric
525cb14a3feSDimitry Andrictemplate <class _Tp,
526cb14a3feSDimitry Andric          bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value &&
5270b57cec5SDimitry Andric                 is_trivially_move_assignable<_Tp>::value>
528cb14a3feSDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
5290b57cec5SDimitry Andric  using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
5300b57cec5SDimitry Andric};
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andrictemplate <class _Tp>
533cb14a3feSDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> {
5340b57cec5SDimitry Andric  using value_type = _Tp;
5350b57cec5SDimitry Andric  using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
5360b57cec5SDimitry Andric
537cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base()                                              = default;
538cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt)      = default;
539cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&)                 = default;
540cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
5410b57cec5SDimitry Andric
542cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base&
543cb14a3feSDimitry Andric  operator=(__optional_move_assign_base&& __opt) noexcept(
544cb14a3feSDimitry Andric      is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) {
5455f757f3fSDimitry Andric    this->__assign_from(std::move(__opt));
5460b57cec5SDimitry Andric    return *this;
5470b57cec5SDimitry Andric  }
5480b57cec5SDimitry Andric};
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andrictemplate <class _Tp>
551cb14a3feSDimitry Andricusing __optional_sfinae_ctor_base_t =
552cb14a3feSDimitry Andric    __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >;
5530b57cec5SDimitry Andric
5540b57cec5SDimitry Andrictemplate <class _Tp>
555cb14a3feSDimitry Andricusing __optional_sfinae_assign_base_t =
556cb14a3feSDimitry Andric    __sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
557cb14a3feSDimitry Andric                          (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >;
5580b57cec5SDimitry Andric
5590b57cec5SDimitry Andrictemplate <class _Tp>
5600eae32dcSDimitry Andricclass optional;
56106c3fb27SDimitry Andric
56206c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 20
56306c3fb27SDimitry Andric
56406c3fb27SDimitry Andrictemplate <class _Tp>
56506c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); };
56606c3fb27SDimitry Andric
56706c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
56806c3fb27SDimitry Andric
5690eae32dcSDimitry Andrictemplate <class _Tp>
5700eae32dcSDimitry Andricstruct __is_std_optional : false_type {};
571cb14a3feSDimitry Andrictemplate <class _Tp>
572cb14a3feSDimitry Andricstruct __is_std_optional<optional<_Tp>> : true_type {};
5730eae32dcSDimitry Andric
5740eae32dcSDimitry Andrictemplate <class _Tp>
57506c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional
576cb14a3feSDimitry Andric    : private __optional_move_assign_base<_Tp>,
577cb14a3feSDimitry Andric      private __optional_sfinae_ctor_base_t<_Tp>,
578cb14a3feSDimitry Andric      private __optional_sfinae_assign_base_t<_Tp> {
5790b57cec5SDimitry Andric  using __base = __optional_move_assign_base<_Tp>;
580cb14a3feSDimitry Andric
5810b57cec5SDimitry Andricpublic:
5820b57cec5SDimitry Andric  using value_type = _Tp;
5830b57cec5SDimitry Andric
5840fca6ea1SDimitry Andric  using __trivially_relocatable = conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
5850fca6ea1SDimitry Andric
5860b57cec5SDimitry Andricprivate:
5870b57cec5SDimitry Andric  // Disable the reference extension using this static assert.
588bdd1243dSDimitry Andric  static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,
5890b57cec5SDimitry Andric                "instantiation of optional with in_place_t is ill-formed");
590bdd1243dSDimitry Andric  static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>,
5910b57cec5SDimitry Andric                "instantiation of optional with nullopt_t is ill-formed");
592cb14a3feSDimitry Andric  static_assert(!is_reference_v<value_type>, "instantiation of optional with a reference type is ill-formed");
593cb14a3feSDimitry Andric  static_assert(is_destructible_v<value_type>, "instantiation of optional with a non-destructible type is ill-formed");
594cb14a3feSDimitry Andric  static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed");
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric  // LWG2756: conditionally explicit conversion from _Up
5970b57cec5SDimitry Andric  struct _CheckOptionalArgsConstructor {
5980b57cec5SDimitry Andric    template <class _Up>
59906c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
600cb14a3feSDimitry Andric      return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
6010b57cec5SDimitry Andric    }
6020b57cec5SDimitry Andric
6030b57cec5SDimitry Andric    template <class _Up>
60406c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
605cb14a3feSDimitry Andric      return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
6060b57cec5SDimitry Andric    }
6070b57cec5SDimitry Andric  };
6080b57cec5SDimitry Andric  template <class _Up>
609cb14a3feSDimitry Andric  using _CheckOptionalArgsCtor =
610cb14a3feSDimitry Andric      _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
6115f757f3fSDimitry Andric               (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value),
6120b57cec5SDimitry Andric           _CheckOptionalArgsConstructor,
613cb14a3feSDimitry Andric           __check_tuple_constructor_fail >;
6140b57cec5SDimitry Andric  template <class _QualUp>
6150b57cec5SDimitry Andric  struct _CheckOptionalLikeConstructor {
6160b57cec5SDimitry Andric    template <class _Up, class _Opt = optional<_Up>>
617cb14a3feSDimitry Andric    using __check_constructible_from_opt =
618cb14a3feSDimitry Andric        _Or< is_constructible<_Tp, _Opt&>,
6190b57cec5SDimitry Andric             is_constructible<_Tp, _Opt const&>,
6200b57cec5SDimitry Andric             is_constructible<_Tp, _Opt&&>,
6210b57cec5SDimitry Andric             is_constructible<_Tp, _Opt const&&>,
6220b57cec5SDimitry Andric             is_convertible<_Opt&, _Tp>,
6230b57cec5SDimitry Andric             is_convertible<_Opt const&, _Tp>,
6240b57cec5SDimitry Andric             is_convertible<_Opt&&, _Tp>,
625cb14a3feSDimitry Andric             is_convertible<_Opt const&&, _Tp> >;
6260b57cec5SDimitry Andric    template <class _Up, class _Opt = optional<_Up>>
627cb14a3feSDimitry Andric    using __check_assignable_from_opt =
628cb14a3feSDimitry Andric        _Or< is_assignable<_Tp&, _Opt&>,
6290b57cec5SDimitry Andric             is_assignable<_Tp&, _Opt const&>,
6300b57cec5SDimitry Andric             is_assignable<_Tp&, _Opt&&>,
631cb14a3feSDimitry Andric             is_assignable<_Tp&, _Opt const&&> >;
6320b57cec5SDimitry Andric    template <class _Up, class _QUp = _QualUp>
63306c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
6340b57cec5SDimitry Andric      return is_convertible<_QUp, _Tp>::value &&
6355f757f3fSDimitry Andric             (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
6360b57cec5SDimitry Andric    }
6370b57cec5SDimitry Andric    template <class _Up, class _QUp = _QualUp>
63806c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
6390b57cec5SDimitry Andric      return !is_convertible<_QUp, _Tp>::value &&
6405f757f3fSDimitry Andric             (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
6410b57cec5SDimitry Andric    }
6420b57cec5SDimitry Andric    template <class _Up, class _QUp = _QualUp>
64306c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
644e8d8bef9SDimitry Andric      // Construction and assignability of _QUp to _Tp has already been
6450b57cec5SDimitry Andric      // checked.
646cb14a3feSDimitry Andric      return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value;
6470b57cec5SDimitry Andric    }
6480b57cec5SDimitry Andric  };
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric  template <class _Up, class _QualUp>
651cb14a3feSDimitry Andric  using _CheckOptionalLikeCtor =
652cb14a3feSDimitry Andric      _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
6530b57cec5SDimitry Andric           _CheckOptionalLikeConstructor<_QualUp>,
654cb14a3feSDimitry Andric           __check_tuple_constructor_fail >;
6550b57cec5SDimitry Andric  template <class _Up, class _QualUp>
656cb14a3feSDimitry Andric  using _CheckOptionalLikeAssign =
657cb14a3feSDimitry Andric      _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,
6580b57cec5SDimitry Andric           _CheckOptionalLikeConstructor<_QualUp>,
659cb14a3feSDimitry Andric           __check_tuple_constructor_fail >;
6600eae32dcSDimitry Andric
6610b57cec5SDimitry Andricpublic:
6625f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
6635f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default;
6645f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&)      = default;
6655f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {}
6660b57cec5SDimitry Andric
667cb14a3feSDimitry Andric  template <
668cb14a3feSDimitry Andric      class _InPlaceT,
669cb14a3feSDimitry Andric      class... _Args,
670cb14a3feSDimitry Andric      class = enable_if_t< _And< _IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...> >::value > >
671cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
6725f757f3fSDimitry Andric      : __base(in_place, std::forward<_Args>(__args)...) {}
6730b57cec5SDimitry Andric
674cb14a3feSDimitry Andric  template <class _Up,
675cb14a3feSDimitry Andric            class... _Args,
676cb14a3feSDimitry Andric            class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> >
677cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
6785f757f3fSDimitry Andric      : __base(in_place, __il, std::forward<_Args>(__args)...) {}
6790b57cec5SDimitry Andric
680cb14a3feSDimitry Andric  template <class _Up                                                                         = value_type,
681cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
682cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
6830b57cec5SDimitry Andric
684cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
685cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
6860b57cec5SDimitry Andric
6870b57cec5SDimitry Andric  // LWG2756: conditionally explicit conversion from const optional<_Up>&
688cb14a3feSDimitry Andric  template <class _Up,
689cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
690cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
6910b57cec5SDimitry Andric    this->__construct_from(__v);
6920b57cec5SDimitry Andric  }
693cb14a3feSDimitry Andric  template <class _Up,
694cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
695cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
6960b57cec5SDimitry Andric    this->__construct_from(__v);
6970b57cec5SDimitry Andric  }
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric  // LWG2756: conditionally explicit conversion from optional<_Up>&&
700cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
701cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
7025f757f3fSDimitry Andric    this->__construct_from(std::move(__v));
7030b57cec5SDimitry Andric  }
704cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
705cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
7065f757f3fSDimitry Andric    this->__construct_from(std::move(__v));
7070b57cec5SDimitry Andric  }
7080b57cec5SDimitry Andric
70906c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
710*62987288SDimitry Andric  template <class _Tag,
711*62987288SDimitry Andric            class _Fp,
712*62987288SDimitry Andric            class... _Args,
713*62987288SDimitry Andric            __enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
714*62987288SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
715cb14a3feSDimitry Andric      : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
7160eae32dcSDimitry Andric#  endif
7170eae32dcSDimitry Andric
718cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept {
7190b57cec5SDimitry Andric    reset();
7200b57cec5SDimitry Andric    return *this;
7210b57cec5SDimitry Andric  }
7220b57cec5SDimitry Andric
72306c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
72406c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&)      = default;
7250b57cec5SDimitry Andric
7260b57cec5SDimitry Andric  // LWG2756
727cb14a3feSDimitry Andric  template <
728cb14a3feSDimitry Andric      class _Up = value_type,
729cb14a3feSDimitry Andric      class     = enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Up>, optional>,
730cb14a3feSDimitry Andric                                     _Or< _IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>> >,
7310b57cec5SDimitry Andric                                     is_constructible<value_type, _Up>,
732cb14a3feSDimitry Andric                                     is_assignable<value_type&, _Up> >::value> >
733cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
7340b57cec5SDimitry Andric    if (this->has_value())
7355f757f3fSDimitry Andric      this->__get() = std::forward<_Up>(__v);
7360b57cec5SDimitry Andric    else
7375f757f3fSDimitry Andric      this->__construct(std::forward<_Up>(__v));
7380b57cec5SDimitry Andric    return *this;
7390b57cec5SDimitry Andric  }
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric  // LWG2756
742cb14a3feSDimitry Andric  template <class _Up,
743cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
744cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
7450b57cec5SDimitry Andric    this->__assign_from(__v);
7460b57cec5SDimitry Andric    return *this;
7470b57cec5SDimitry Andric  }
7480b57cec5SDimitry Andric
7490b57cec5SDimitry Andric  // LWG2756
750cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
751cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
7525f757f3fSDimitry Andric    this->__assign_from(std::move(__v));
7530b57cec5SDimitry Andric    return *this;
7540b57cec5SDimitry Andric  }
7550b57cec5SDimitry Andric
756cb14a3feSDimitry Andric  template <class... _Args, class = enable_if_t< is_constructible_v<value_type, _Args...> > >
757cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
7580b57cec5SDimitry Andric    reset();
7595f757f3fSDimitry Andric    this->__construct(std::forward<_Args>(__args)...);
7600b57cec5SDimitry Andric    return this->__get();
7610b57cec5SDimitry Andric  }
7620b57cec5SDimitry Andric
763cb14a3feSDimitry Andric  template <class _Up,
764cb14a3feSDimitry Andric            class... _Args,
765cb14a3feSDimitry Andric            class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...> > >
766cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
7670b57cec5SDimitry Andric    reset();
7685f757f3fSDimitry Andric    this->__construct(__il, std::forward<_Args>(__args)...);
7690b57cec5SDimitry Andric    return this->__get();
7700b57cec5SDimitry Andric  }
7710b57cec5SDimitry Andric
772cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
773cb14a3feSDimitry Andric  swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<value_type> && is_nothrow_swappable_v<value_type>) {
774cb14a3feSDimitry Andric    if (this->has_value() == __opt.has_value()) {
7755f757f3fSDimitry Andric      using std::swap;
7760b57cec5SDimitry Andric      if (this->has_value())
7770b57cec5SDimitry Andric        swap(this->__get(), __opt.__get());
778cb14a3feSDimitry Andric    } else {
779cb14a3feSDimitry Andric      if (this->has_value()) {
7805f757f3fSDimitry Andric        __opt.__construct(std::move(this->__get()));
7810b57cec5SDimitry Andric        reset();
782cb14a3feSDimitry Andric      } else {
7835f757f3fSDimitry Andric        this->__construct(std::move(__opt.__get()));
7840b57cec5SDimitry Andric        __opt.reset();
7850b57cec5SDimitry Andric      }
7860b57cec5SDimitry Andric    }
7870b57cec5SDimitry Andric  }
7880b57cec5SDimitry Andric
7890fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const noexcept {
79006c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
7915f757f3fSDimitry Andric    return std::addressof(this->__get());
7920b57cec5SDimitry Andric  }
7930b57cec5SDimitry Andric
7940fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() noexcept {
79506c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
7965f757f3fSDimitry Andric    return std::addressof(this->__get());
7970b57cec5SDimitry Andric  }
7980b57cec5SDimitry Andric
799cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept {
80006c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8010b57cec5SDimitry Andric    return this->__get();
8020b57cec5SDimitry Andric  }
8030b57cec5SDimitry Andric
804cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept {
80506c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8060b57cec5SDimitry Andric    return this->__get();
8070b57cec5SDimitry Andric  }
8080b57cec5SDimitry Andric
809cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept {
81006c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8115f757f3fSDimitry Andric    return std::move(this->__get());
8120b57cec5SDimitry Andric  }
8130b57cec5SDimitry Andric
814cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept {
81506c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8165f757f3fSDimitry Andric    return std::move(this->__get());
8170b57cec5SDimitry Andric  }
8180b57cec5SDimitry Andric
819cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); }
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric  using __base::__get;
822cb14a3feSDimitry Andric  using __base::has_value;
8230b57cec5SDimitry Andric
824cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const& value() const& {
8250b57cec5SDimitry Andric    if (!this->has_value())
8260b57cec5SDimitry Andric      __throw_bad_optional_access();
8270b57cec5SDimitry Andric    return this->__get();
8280b57cec5SDimitry Andric  }
8290b57cec5SDimitry Andric
830cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& value() & {
8310b57cec5SDimitry Andric    if (!this->has_value())
8320b57cec5SDimitry Andric      __throw_bad_optional_access();
8330b57cec5SDimitry Andric    return this->__get();
8340b57cec5SDimitry Andric  }
8350b57cec5SDimitry Andric
836cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& value() && {
8370b57cec5SDimitry Andric    if (!this->has_value())
8380b57cec5SDimitry Andric      __throw_bad_optional_access();
8395f757f3fSDimitry Andric    return std::move(this->__get());
8400b57cec5SDimitry Andric  }
8410b57cec5SDimitry Andric
842cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const&& value() const&& {
8430b57cec5SDimitry Andric    if (!this->has_value())
8440b57cec5SDimitry Andric      __throw_bad_optional_access();
8455f757f3fSDimitry Andric    return std::move(this->__get());
8460b57cec5SDimitry Andric  }
8470b57cec5SDimitry Andric
8480b57cec5SDimitry Andric  template <class _Up>
849cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) const& {
850cb14a3feSDimitry Andric    static_assert(is_copy_constructible_v<value_type>, "optional<T>::value_or: T must be copy constructible");
851cb14a3feSDimitry Andric    static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T");
852cb14a3feSDimitry Andric    return this->has_value() ? this->__get() : static_cast<value_type>(std::forward<_Up>(__v));
8530b57cec5SDimitry Andric  }
8540b57cec5SDimitry Andric
8550b57cec5SDimitry Andric  template <class _Up>
856cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) && {
857cb14a3feSDimitry Andric    static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible");
858cb14a3feSDimitry Andric    static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T");
859cb14a3feSDimitry Andric    return this->has_value() ? std::move(this->__get()) : static_cast<value_type>(std::forward<_Up>(__v));
8600b57cec5SDimitry Andric  }
8610b57cec5SDimitry Andric
86206c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
8630eae32dcSDimitry Andric  template <class _Func>
864cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) & {
8650eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&>;
8660eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8670eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
8680eae32dcSDimitry Andric    if (*this)
8695f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), value());
8700eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
8710eae32dcSDimitry Andric  }
8720eae32dcSDimitry Andric
8730eae32dcSDimitry Andric  template <class _Func>
874cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) const& {
8750eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&>;
8760eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8770eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
8780eae32dcSDimitry Andric    if (*this)
8795f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), value());
8800eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
8810eae32dcSDimitry Andric  }
8820eae32dcSDimitry Andric
8830eae32dcSDimitry Andric  template <class _Func>
884cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) && {
8850eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&&>;
8860eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8870eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
8880eae32dcSDimitry Andric    if (*this)
8895f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), std::move(value()));
8900eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
8910eae32dcSDimitry Andric  }
8920eae32dcSDimitry Andric
8930eae32dcSDimitry Andric  template <class _Func>
894cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
8950eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&&>;
8960eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8970eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
8980eae32dcSDimitry Andric    if (*this)
8995f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), std::move(value()));
9000eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
9010eae32dcSDimitry Andric  }
9020eae32dcSDimitry Andric
9030eae32dcSDimitry Andric  template <class _Func>
904cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) & {
9050eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
9060eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
907cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
908cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
9090eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
9100eae32dcSDimitry Andric    if (*this)
9115f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
9120eae32dcSDimitry Andric    return optional<_Up>();
9130eae32dcSDimitry Andric  }
9140eae32dcSDimitry Andric
9150eae32dcSDimitry Andric  template <class _Func>
916cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const& {
9170eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
9180eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
919cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
920cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
9210eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
9220eae32dcSDimitry Andric    if (*this)
9235f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
9240eae32dcSDimitry Andric    return optional<_Up>();
9250eae32dcSDimitry Andric  }
9260eae32dcSDimitry Andric
9270eae32dcSDimitry Andric  template <class _Func>
928cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) && {
9290eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
9300eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
931cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
932cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
9330eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
9340eae32dcSDimitry Andric    if (*this)
9355f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
9360eae32dcSDimitry Andric    return optional<_Up>();
9370eae32dcSDimitry Andric  }
9380eae32dcSDimitry Andric
9390eae32dcSDimitry Andric  template <class _Func>
940cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const&& {
9410eae32dcSDimitry Andric    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
9420eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
943cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
944cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
9450eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
9460eae32dcSDimitry Andric    if (*this)
9475f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
9480eae32dcSDimitry Andric    return optional<_Up>();
9490eae32dcSDimitry Andric  }
9500eae32dcSDimitry Andric
9510eae32dcSDimitry Andric  template <invocable _Func>
952cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
953cb14a3feSDimitry Andric    requires is_copy_constructible_v<value_type>
954cb14a3feSDimitry Andric  {
9550eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
9560eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
9570eae32dcSDimitry Andric    if (*this)
9580eae32dcSDimitry Andric      return *this;
9595f757f3fSDimitry Andric    return std::forward<_Func>(__f)();
9600eae32dcSDimitry Andric  }
9610eae32dcSDimitry Andric
9620eae32dcSDimitry Andric  template <invocable _Func>
963cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
964cb14a3feSDimitry Andric    requires is_move_constructible_v<value_type>
965cb14a3feSDimitry Andric  {
9660eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
9670eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
9680eae32dcSDimitry Andric    if (*this)
9695f757f3fSDimitry Andric      return std::move(*this);
9705f757f3fSDimitry Andric    return std::forward<_Func>(__f)();
9710eae32dcSDimitry Andric  }
97206c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 23
9730eae32dcSDimitry Andric
9740b57cec5SDimitry Andric  using __base::reset;
9750b57cec5SDimitry Andric};
9760b57cec5SDimitry Andric
977349cc55cSDimitry Andric#  if _LIBCPP_STD_VER >= 17
97804eeddc0SDimitry Andrictemplate <class _Tp>
97904eeddc0SDimitry Andricoptional(_Tp) -> optional<_Tp>;
9800b57cec5SDimitry Andric#  endif
9810b57cec5SDimitry Andric
9820b57cec5SDimitry Andric// Comparisons between optionals
9830b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
984cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
985cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
986cb14a3feSDimitry Andric    bool >
987cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) {
9880b57cec5SDimitry Andric  if (static_cast<bool>(__x) != static_cast<bool>(__y))
9890b57cec5SDimitry Andric    return false;
9900b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
9910b57cec5SDimitry Andric    return true;
9920b57cec5SDimitry Andric  return *__x == *__y;
9930b57cec5SDimitry Andric}
9940b57cec5SDimitry Andric
9950b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
996cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
997cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
998cb14a3feSDimitry Andric    bool >
999cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) {
10000b57cec5SDimitry Andric  if (static_cast<bool>(__x) != static_cast<bool>(__y))
10010b57cec5SDimitry Andric    return true;
10020b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10030b57cec5SDimitry Andric    return false;
10040b57cec5SDimitry Andric  return *__x != *__y;
10050b57cec5SDimitry Andric}
10060b57cec5SDimitry Andric
10070b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1008cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1009cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
1010cb14a3feSDimitry Andric    bool >
1011cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) {
10120b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10130b57cec5SDimitry Andric    return false;
10140b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10150b57cec5SDimitry Andric    return true;
10160b57cec5SDimitry Andric  return *__x < *__y;
10170b57cec5SDimitry Andric}
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1020cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1021cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
1022cb14a3feSDimitry Andric    bool >
1023cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) {
10240b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10250b57cec5SDimitry Andric    return false;
10260b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10270b57cec5SDimitry Andric    return true;
10280b57cec5SDimitry Andric  return *__x > *__y;
10290b57cec5SDimitry Andric}
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1032cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1033cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
1034cb14a3feSDimitry Andric    bool >
1035cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) {
10360b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10370b57cec5SDimitry Andric    return true;
10380b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10390b57cec5SDimitry Andric    return false;
10400b57cec5SDimitry Andric  return *__x <= *__y;
10410b57cec5SDimitry Andric}
10420b57cec5SDimitry Andric
10430b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1044cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1045cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
1046cb14a3feSDimitry Andric    bool >
1047cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) {
10480b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10490b57cec5SDimitry Andric    return true;
10500b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10510b57cec5SDimitry Andric    return false;
10520b57cec5SDimitry Andric  return *__x >= *__y;
10530b57cec5SDimitry Andric}
10540b57cec5SDimitry Andric
105506c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 20
105606c3fb27SDimitry Andric
105706c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up>
105806c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
105906c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) {
106006c3fb27SDimitry Andric  if (__x && __y)
106106c3fb27SDimitry Andric    return *__x <=> *__y;
106206c3fb27SDimitry Andric  return __x.has_value() <=> __y.has_value();
106306c3fb27SDimitry Andric}
106406c3fb27SDimitry Andric
106506c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
106606c3fb27SDimitry Andric
10670b57cec5SDimitry Andric// Comparisons with nullopt
10680b57cec5SDimitry Andrictemplate <class _Tp>
1069cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept {
10700b57cec5SDimitry Andric  return !static_cast<bool>(__x);
10710b57cec5SDimitry Andric}
10720b57cec5SDimitry Andric
107306c3fb27SDimitry Andric#  if _LIBCPP_STD_VER <= 17
107406c3fb27SDimitry Andric
10750b57cec5SDimitry Andrictemplate <class _Tp>
1076cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept {
10770b57cec5SDimitry Andric  return !static_cast<bool>(__x);
10780b57cec5SDimitry Andric}
10790b57cec5SDimitry Andric
10800b57cec5SDimitry Andrictemplate <class _Tp>
1081cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept {
10820b57cec5SDimitry Andric  return static_cast<bool>(__x);
10830b57cec5SDimitry Andric}
10840b57cec5SDimitry Andric
10850b57cec5SDimitry Andrictemplate <class _Tp>
1086cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept {
10870b57cec5SDimitry Andric  return static_cast<bool>(__x);
10880b57cec5SDimitry Andric}
10890b57cec5SDimitry Andric
10900b57cec5SDimitry Andrictemplate <class _Tp>
1091cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept {
10920b57cec5SDimitry Andric  return false;
10930b57cec5SDimitry Andric}
10940b57cec5SDimitry Andric
10950b57cec5SDimitry Andrictemplate <class _Tp>
1096cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept {
10970b57cec5SDimitry Andric  return static_cast<bool>(__x);
10980b57cec5SDimitry Andric}
10990b57cec5SDimitry Andric
11000b57cec5SDimitry Andrictemplate <class _Tp>
1101cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept {
11020b57cec5SDimitry Andric  return !static_cast<bool>(__x);
11030b57cec5SDimitry Andric}
11040b57cec5SDimitry Andric
11050b57cec5SDimitry Andrictemplate <class _Tp>
1106cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept {
11070b57cec5SDimitry Andric  return true;
11080b57cec5SDimitry Andric}
11090b57cec5SDimitry Andric
11100b57cec5SDimitry Andrictemplate <class _Tp>
1111cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept {
11120b57cec5SDimitry Andric  return static_cast<bool>(__x);
11130b57cec5SDimitry Andric}
11140b57cec5SDimitry Andric
11150b57cec5SDimitry Andrictemplate <class _Tp>
1116cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept {
11170b57cec5SDimitry Andric  return false;
11180b57cec5SDimitry Andric}
11190b57cec5SDimitry Andric
11200b57cec5SDimitry Andrictemplate <class _Tp>
1121cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept {
11220b57cec5SDimitry Andric  return true;
11230b57cec5SDimitry Andric}
11240b57cec5SDimitry Andric
11250b57cec5SDimitry Andrictemplate <class _Tp>
1126cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept {
11270b57cec5SDimitry Andric  return !static_cast<bool>(__x);
11280b57cec5SDimitry Andric}
11290b57cec5SDimitry Andric
113006c3fb27SDimitry Andric#  else // _LIBCPP_STD_VER <= 17
113106c3fb27SDimitry Andric
113206c3fb27SDimitry Andrictemplate <class _Tp>
113306c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept {
113406c3fb27SDimitry Andric  return __x.has_value() <=> false;
113506c3fb27SDimitry Andric}
113606c3fb27SDimitry Andric
113706c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER <= 17
113806c3fb27SDimitry Andric
11390b57cec5SDimitry Andric// Comparisons with T
11400b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1141cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1142cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
1143cb14a3feSDimitry Andric    bool >
1144cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) {
11450b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x == __v : false;
11460b57cec5SDimitry Andric}
11470b57cec5SDimitry Andric
11480b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1149cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1150cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
1151cb14a3feSDimitry Andric    bool >
1152cb14a3feSDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) {
11530b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v == *__x : false;
11540b57cec5SDimitry Andric}
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1157cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1158cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
1159cb14a3feSDimitry Andric    bool >
1160cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) {
11610b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x != __v : true;
11620b57cec5SDimitry Andric}
11630b57cec5SDimitry Andric
11640b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1165cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1166cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
1167cb14a3feSDimitry Andric    bool >
1168cb14a3feSDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) {
11690b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v != *__x : true;
11700b57cec5SDimitry Andric}
11710b57cec5SDimitry Andric
11720b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1173cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1174cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
1175cb14a3feSDimitry Andric    bool >
1176cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) {
11770b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x < __v : true;
11780b57cec5SDimitry Andric}
11790b57cec5SDimitry Andric
11800b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1181cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1182cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
1183cb14a3feSDimitry Andric    bool >
1184cb14a3feSDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) {
11850b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v < *__x : false;
11860b57cec5SDimitry Andric}
11870b57cec5SDimitry Andric
11880b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1189cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1190cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
1191cb14a3feSDimitry Andric    bool >
1192cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) {
11930b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x <= __v : true;
11940b57cec5SDimitry Andric}
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1197cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1198cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
1199cb14a3feSDimitry Andric    bool >
1200cb14a3feSDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) {
12010b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v <= *__x : false;
12020b57cec5SDimitry Andric}
12030b57cec5SDimitry Andric
12040b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1205cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1206cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
1207cb14a3feSDimitry Andric    bool >
1208cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) {
12090b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x > __v : false;
12100b57cec5SDimitry Andric}
12110b57cec5SDimitry Andric
12120b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1213cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1214cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
1215cb14a3feSDimitry Andric    bool >
1216cb14a3feSDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) {
12170b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v > *__x : true;
12180b57cec5SDimitry Andric}
12190b57cec5SDimitry Andric
12200b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1221cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1222cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
1223cb14a3feSDimitry Andric    bool >
1224cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) {
12250b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x >= __v : false;
12260b57cec5SDimitry Andric}
12270b57cec5SDimitry Andric
12280b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1229cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1230cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
1231cb14a3feSDimitry Andric    bool >
1232cb14a3feSDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) {
12330b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v >= *__x : true;
12340b57cec5SDimitry Andric}
12350b57cec5SDimitry Andric
123606c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 20
123706c3fb27SDimitry Andric
123806c3fb27SDimitry Andrictemplate <class _Tp, class _Up>
123906c3fb27SDimitry Andric  requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up>
124006c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
124106c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) {
124206c3fb27SDimitry Andric  return __x.has_value() ? *__x <=> __v : strong_ordering::less;
124306c3fb27SDimitry Andric}
124406c3fb27SDimitry Andric
124506c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
124606c3fb27SDimitry Andric
12470b57cec5SDimitry Andrictemplate <class _Tp>
12480fca6ea1SDimitry Andricinline _LIBCPP_HIDE_FROM_ABI
12490fca6ea1SDimitry Andric_LIBCPP_CONSTEXPR_SINCE_CXX20 enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void >
1250cb14a3feSDimitry Andricswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) {
12510b57cec5SDimitry Andric  __x.swap(__y);
12520b57cec5SDimitry Andric}
12530b57cec5SDimitry Andric
12540b57cec5SDimitry Andrictemplate <class _Tp>
1255cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<decay_t<_Tp>> make_optional(_Tp&& __v) {
12565f757f3fSDimitry Andric  return optional<decay_t<_Tp>>(std::forward<_Tp>(__v));
12570b57cec5SDimitry Andric}
12580b57cec5SDimitry Andric
12590b57cec5SDimitry Andrictemplate <class _Tp, class... _Args>
1260cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(_Args&&... __args) {
12615f757f3fSDimitry Andric  return optional<_Tp>(in_place, std::forward<_Args>(__args)...);
12620b57cec5SDimitry Andric}
12630b57cec5SDimitry Andric
12640b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args>
1265cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) {
12665f757f3fSDimitry Andric  return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...);
12670b57cec5SDimitry Andric}
12680b57cec5SDimitry Andric
12690b57cec5SDimitry Andrictemplate <class _Tp>
1270cb14a3feSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > {
1271fe6060f1SDimitry Andric#  if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1272fe6060f1SDimitry Andric  _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1273fe6060f1SDimitry Andric  _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
1274fe6060f1SDimitry Andric#  endif
12750b57cec5SDimitry Andric
1276cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const {
12770b57cec5SDimitry Andric    return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
12780b57cec5SDimitry Andric  }
12790b57cec5SDimitry Andric};
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
12820b57cec5SDimitry Andric
128306c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17
128406c3fb27SDimitry Andric
128506c3fb27SDimitry Andric_LIBCPP_POP_MACROS
12860b57cec5SDimitry Andric
1287bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
1288bdd1243dSDimitry Andric#  include <atomic>
1289bdd1243dSDimitry Andric#  include <climits>
1290bdd1243dSDimitry Andric#  include <concepts>
1291bdd1243dSDimitry Andric#  include <ctime>
1292bdd1243dSDimitry Andric#  include <iterator>
12930fca6ea1SDimitry Andric#  include <limits>
1294bdd1243dSDimitry Andric#  include <memory>
1295bdd1243dSDimitry Andric#  include <ratio>
12965f757f3fSDimitry Andric#  include <stdexcept>
1297bdd1243dSDimitry Andric#  include <tuple>
129806c3fb27SDimitry Andric#  include <type_traits>
1299bdd1243dSDimitry Andric#  include <typeinfo>
1300bdd1243dSDimitry Andric#  include <utility>
1301bdd1243dSDimitry Andric#  include <variant>
1302bdd1243dSDimitry Andric#endif
1303bdd1243dSDimitry Andric
13040b57cec5SDimitry Andric#endif // _LIBCPP_OPTIONAL
1305