xref: /freebsd/contrib/llvm-project/libcxx/include/optional (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_OPTIONAL
110b57cec5SDimitry Andric#define _LIBCPP_OPTIONAL
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    optional synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric// C++1z
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricnamespace std {
1906c3fb27SDimitry Andric  // [optional.optional], class template optional
2006c3fb27SDimitry Andric  template <class T>
2106c3fb27SDimitry Andric    class optional;
220b57cec5SDimitry Andric
2306c3fb27SDimitry Andric  template<class T>
2406c3fb27SDimitry Andric    concept is-derived-from-optional = requires(const T& t) {       // exposition only
2506c3fb27SDimitry Andric      []<class U>(const optional<U>&){ }(t);
2606c3fb27SDimitry Andric    };
2706c3fb27SDimitry Andric
2806c3fb27SDimitry Andric  // [optional.nullopt], no-value state indicator
290b57cec5SDimitry Andric  struct nullopt_t{see below };
300b57cec5SDimitry Andric  inline constexpr nullopt_t nullopt(unspecified );
310b57cec5SDimitry Andric
3206c3fb27SDimitry Andric  // [optional.bad.access], class bad_optional_access
330b57cec5SDimitry Andric  class bad_optional_access;
340b57cec5SDimitry Andric
3506c3fb27SDimitry Andric  // [optional.relops], relational operators
360b57cec5SDimitry Andric  template <class T, class U>
370b57cec5SDimitry Andric    constexpr bool operator==(const optional<T>&, const optional<U>&);
380b57cec5SDimitry Andric  template <class T, class U>
390b57cec5SDimitry Andric    constexpr bool operator!=(const optional<T>&, const optional<U>&);
400b57cec5SDimitry Andric  template <class T, class U>
410b57cec5SDimitry Andric    constexpr bool operator<(const optional<T>&, const optional<U>&);
420b57cec5SDimitry Andric  template <class T, class U>
430b57cec5SDimitry Andric    constexpr bool operator>(const optional<T>&, const optional<U>&);
440b57cec5SDimitry Andric  template <class T, class U>
450b57cec5SDimitry Andric    constexpr bool operator<=(const optional<T>&, const optional<U>&);
460b57cec5SDimitry Andric  template <class T, class U>
470b57cec5SDimitry Andric    constexpr bool operator>=(const optional<T>&, const optional<U>&);
4806c3fb27SDimitry Andric  template<class T, three_way_comparable_with<T> U>
4906c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
5006c3fb27SDimitry Andric      operator<=>(const optional<T>&, const optional<U>&); // since C++20
510b57cec5SDimitry Andric
5206c3fb27SDimitry Andric  // [optional.nullops], comparison with nullopt
530b57cec5SDimitry Andric  template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
5406c3fb27SDimitry Andric  template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17
5506c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17
5606c3fb27SDimitry Andric  template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17
5706c3fb27SDimitry Andric  template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;  // until C++17
5806c3fb27SDimitry Andric  template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;  // until C++17
5906c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17
6006c3fb27SDimitry Andric  template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17
6106c3fb27SDimitry Andric  template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;  // until C++17
6206c3fb27SDimitry Andric  template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;  // until C++17
6306c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17
6406c3fb27SDimitry Andric  template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17
6506c3fb27SDimitry Andric  template<class T>
6606c3fb27SDimitry Andric    constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept;     // since C++20
670b57cec5SDimitry Andric
6806c3fb27SDimitry Andric  // [optional.comp.with.t], comparison with T
690b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator==(const optional<T>&, const U&);
700b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator==(const T&, const optional<U>&);
710b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
720b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
730b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<(const optional<T>&, const U&);
740b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<(const T&, const optional<U>&);
750b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
760b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
770b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>(const optional<T>&, const U&);
780b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>(const T&, const optional<U>&);
790b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
800b57cec5SDimitry Andric  template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
8106c3fb27SDimitry Andric  template<class T, class U>
8206c3fb27SDimitry Andric      requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U>
8306c3fb27SDimitry Andric    constexpr compare_three_way_result_t<T, U>
8406c3fb27SDimitry Andric      operator<=>(const optional<T>&, const U&);                                       // since C++20
850b57cec5SDimitry Andric
8606c3fb27SDimitry Andric  // [optional.specalg], specialized algorithms
8706c3fb27SDimitry Andric  template<class T>
8806c3fb27SDimitry Andric    void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
8906c3fb27SDimitry Andric
9006c3fb27SDimitry Andric  template<class T>
9106c3fb27SDimitry Andric    constexpr optional<see below > make_optional(T&&);
920b57cec5SDimitry Andric  template<class T, class... Args>
930b57cec5SDimitry Andric    constexpr optional<T> make_optional(Args&&... args);
940b57cec5SDimitry Andric  template<class T, class U, class... Args>
950b57cec5SDimitry Andric    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
960b57cec5SDimitry Andric
9706c3fb27SDimitry Andric  // [optional.hash], hash support
980b57cec5SDimitry Andric  template<class T> struct hash;
990b57cec5SDimitry Andric  template<class T> struct hash<optional<T>>;
1000b57cec5SDimitry Andric
10106c3fb27SDimitry Andric  template<class T>
10206c3fb27SDimitry Andric  class optional {
1030b57cec5SDimitry Andric  public:
1040b57cec5SDimitry Andric    using value_type = T;
1050b57cec5SDimitry Andric
10606c3fb27SDimitry Andric    // [optional.ctor], constructors
1070b57cec5SDimitry Andric    constexpr optional() noexcept;
1080b57cec5SDimitry Andric    constexpr optional(nullopt_t) noexcept;
109bdd1243dSDimitry Andric    constexpr optional(const optional &);
110bdd1243dSDimitry Andric    constexpr optional(optional &&) noexcept(see below);
11106c3fb27SDimitry Andric    template<class... Args>
11206c3fb27SDimitry Andric      constexpr explicit optional(in_place_t, Args &&...);
1130b57cec5SDimitry Andric    template<class U, class... Args>
1140b57cec5SDimitry Andric      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
1150b57cec5SDimitry Andric    template<class U = T>
11681ad6265SDimitry Andric      constexpr explicit(see-below) optional(U &&);
1170b57cec5SDimitry Andric    template<class U>
11881ad6265SDimitry Andric      explicit(see-below) optional(const optional<U> &);                          // constexpr in C++20
1190b57cec5SDimitry Andric    template<class U>
12081ad6265SDimitry Andric      explicit(see-below) optional(optional<U> &&);                               // constexpr in C++20
1210b57cec5SDimitry Andric
12206c3fb27SDimitry Andric    // [optional.dtor], destructor
123fe6060f1SDimitry Andric    ~optional(); // constexpr in C++20
1240b57cec5SDimitry Andric
12506c3fb27SDimitry Andric    // [optional.assign], assignment
126fe6060f1SDimitry Andric    optional &operator=(nullopt_t) noexcept;                                      // constexpr in C++20
127bdd1243dSDimitry Andric    constexpr optional &operator=(const optional &);
128bdd1243dSDimitry Andric    constexpr optional &operator=(optional &&) noexcept(see below);
129fe6060f1SDimitry Andric    template<class U = T> optional &operator=(U &&);                              // constexpr in C++20
130fe6060f1SDimitry Andric    template<class U> optional &operator=(const optional<U> &);                   // constexpr in C++20
131fe6060f1SDimitry Andric    template<class U> optional &operator=(optional<U> &&);                        // constexpr in C++20
132fe6060f1SDimitry Andric    template<class... Args> T& emplace(Args &&...);                               // constexpr in C++20
13306c3fb27SDimitry Andric    template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
1340b57cec5SDimitry Andric
13506c3fb27SDimitry Andric    // [optional.swap], swap
136fe6060f1SDimitry Andric    void swap(optional &) noexcept(see below ); // constexpr in C++20
1370b57cec5SDimitry Andric
13806c3fb27SDimitry Andric    // [optional.observe], observers
1390b57cec5SDimitry Andric    constexpr T const *operator->() const;
1400b57cec5SDimitry Andric    constexpr T *operator->();
1410b57cec5SDimitry Andric    constexpr T const &operator*() const &;
1420b57cec5SDimitry Andric    constexpr T &operator*() &;
1430b57cec5SDimitry Andric    constexpr T &&operator*() &&;
1440b57cec5SDimitry Andric    constexpr const T &&operator*() const &&;
1450b57cec5SDimitry Andric    constexpr explicit operator bool() const noexcept;
1460b57cec5SDimitry Andric    constexpr bool has_value() const noexcept;
1470b57cec5SDimitry Andric    constexpr T const &value() const &;
1480b57cec5SDimitry Andric    constexpr T &value() &;
1490b57cec5SDimitry Andric    constexpr T &&value() &&;
1500b57cec5SDimitry Andric    constexpr const T &&value() const &&;
1510b57cec5SDimitry Andric    template<class U> constexpr T value_or(U &&) const &;
1520b57cec5SDimitry Andric    template<class U> constexpr T value_or(U &&) &&;
1530b57cec5SDimitry Andric
1540eae32dcSDimitry Andric    // [optional.monadic], monadic operations
1550eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &;         // since C++23
1560eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) &&;        // since C++23
1570eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&;    // since C++23
1580eae32dcSDimitry Andric    template<class F> constexpr auto and_then(F&& f) const&&;   // since C++23
1590eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &;        // since C++23
1600eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) &&;       // since C++23
1610eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&;   // since C++23
1620eae32dcSDimitry Andric    template<class F> constexpr auto transform(F&& f) const&&;  // since C++23
1630eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) &&;     // since C++23
1640eae32dcSDimitry Andric    template<class F> constexpr optional or_else(F&& f) const&; // since C++23
1650eae32dcSDimitry Andric
16606c3fb27SDimitry Andric    // [optional.mod], modifiers
167fe6060f1SDimitry Andric    void reset() noexcept;                                      // constexpr in C++20
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric  private:
1700b57cec5SDimitry Andric    T *val;         // exposition only
1710b57cec5SDimitry Andric  };
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric  template<class T>
1740b57cec5SDimitry Andric    optional(T) -> optional<T>;
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric} // namespace std
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric*/
1790b57cec5SDimitry Andric
18081ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
181e8d8bef9SDimitry Andric#include <__availability>
18206c3fb27SDimitry Andric#include <__compare/compare_three_way_result.h>
18306c3fb27SDimitry Andric#include <__compare/three_way_comparable.h>
1840eae32dcSDimitry Andric#include <__concepts/invocable.h>
185fe6060f1SDimitry Andric#include <__config>
1865f757f3fSDimitry Andric#include <__exception/exception.h>
18781ad6265SDimitry Andric#include <__functional/hash.h>
18881ad6265SDimitry Andric#include <__functional/invoke.h>
18906c3fb27SDimitry Andric#include <__functional/reference_wrapper.h>
19081ad6265SDimitry Andric#include <__functional/unary_function.h>
19106c3fb27SDimitry Andric#include <__memory/addressof.h>
19281ad6265SDimitry Andric#include <__memory/construct_at.h>
19306c3fb27SDimitry Andric#include <__tuple/sfinae_helpers.h>
19406c3fb27SDimitry Andric#include <__type_traits/add_pointer.h>
19506c3fb27SDimitry Andric#include <__type_traits/conditional.h>
19606c3fb27SDimitry Andric#include <__type_traits/conjunction.h>
19706c3fb27SDimitry Andric#include <__type_traits/decay.h>
19806c3fb27SDimitry Andric#include <__type_traits/disjunction.h>
19906c3fb27SDimitry Andric#include <__type_traits/is_array.h>
20006c3fb27SDimitry Andric#include <__type_traits/is_assignable.h>
20106c3fb27SDimitry Andric#include <__type_traits/is_constructible.h>
20206c3fb27SDimitry Andric#include <__type_traits/is_convertible.h>
20306c3fb27SDimitry Andric#include <__type_traits/is_copy_assignable.h>
20406c3fb27SDimitry Andric#include <__type_traits/is_copy_constructible.h>
20506c3fb27SDimitry Andric#include <__type_traits/is_destructible.h>
20606c3fb27SDimitry Andric#include <__type_traits/is_move_assignable.h>
20706c3fb27SDimitry Andric#include <__type_traits/is_move_constructible.h>
20806c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_assignable.h>
20906c3fb27SDimitry Andric#include <__type_traits/is_nothrow_move_constructible.h>
21006c3fb27SDimitry Andric#include <__type_traits/is_object.h>
21106c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
21206c3fb27SDimitry Andric#include <__type_traits/is_scalar.h>
21306c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
21406c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_assignable.h>
21506c3fb27SDimitry Andric#include <__type_traits/is_trivially_copy_constructible.h>
21606c3fb27SDimitry Andric#include <__type_traits/is_trivially_destructible.h>
21706c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_assignable.h>
21806c3fb27SDimitry Andric#include <__type_traits/is_trivially_move_constructible.h>
21906c3fb27SDimitry Andric#include <__type_traits/negation.h>
22006c3fb27SDimitry Andric#include <__type_traits/remove_const.h>
22106c3fb27SDimitry Andric#include <__type_traits/remove_cvref.h>
22206c3fb27SDimitry Andric#include <__type_traits/remove_reference.h>
22306c3fb27SDimitry Andric#include <__utility/declval.h>
22481ad6265SDimitry Andric#include <__utility/forward.h>
22581ad6265SDimitry Andric#include <__utility/in_place.h>
22681ad6265SDimitry Andric#include <__utility/move.h>
22781ad6265SDimitry Andric#include <__utility/swap.h>
22806c3fb27SDimitry Andric#include <__verbose_abort>
2290b57cec5SDimitry Andric#include <initializer_list>
2300b57cec5SDimitry Andric#include <new>
2310b57cec5SDimitry Andric#include <version>
2320b57cec5SDimitry Andric
23381ad6265SDimitry Andric// standard-mandated includes
234bdd1243dSDimitry Andric
235bdd1243dSDimitry Andric// [optional.syn]
23681ad6265SDimitry Andric#include <compare>
23781ad6265SDimitry Andric
2380b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2390b57cec5SDimitry Andric#  pragma GCC system_header
2400b57cec5SDimitry Andric#endif
2410b57cec5SDimitry Andric
24206c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS
24306c3fb27SDimitry Andric#include <__undef_macros>
24406c3fb27SDimitry Andric
2450b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace
2460b57cec5SDimitry Andric{
2470b57cec5SDimitry Andric
248*cb14a3feSDimitry Andricclass _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public exception {
2490b57cec5SDimitry Andricpublic:
2505f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT                                      = default;
2515f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT            = default;
2525f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default;
2530b57cec5SDimitry Andric  // Get the key function ~bad_optional_access() into the dylib
254bdd1243dSDimitry Andric  ~bad_optional_access() _NOEXCEPT override;
255bdd1243dSDimitry Andric  const char* what() const _NOEXCEPT override;
2560b57cec5SDimitry Andric};
2570b57cec5SDimitry Andric
2580eae32dcSDimitry Andric} // namespace std
2590b57cec5SDimitry Andric
26006c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 17
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
2630b57cec5SDimitry Andric
264*cb14a3feSDimitry Andric_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS void
265*cb14a3feSDimitry Andric__throw_bad_optional_access() {
26606c3fb27SDimitry Andric#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
2670b57cec5SDimitry Andric  throw bad_optional_access();
2680b57cec5SDimitry Andric#  else
26906c3fb27SDimitry Andric  _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode");
2700b57cec5SDimitry Andric#  endif
2710b57cec5SDimitry Andric}
2720b57cec5SDimitry Andric
273*cb14a3feSDimitry Andricstruct nullopt_t {
274*cb14a3feSDimitry Andric  struct __secret_tag {
275*cb14a3feSDimitry Andric    explicit __secret_tag() = default;
276*cb14a3feSDimitry Andric  };
2775f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
2780b57cec5SDimitry Andric};
2790b57cec5SDimitry Andric
280349cc55cSDimitry Andricinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
2810b57cec5SDimitry Andric
2820eae32dcSDimitry Andricstruct __optional_construct_from_invoke_tag {};
2830eae32dcSDimitry Andric
2840b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
2850b57cec5SDimitry Andricstruct __optional_destruct_base;
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andrictemplate <class _Tp>
288*cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, false> {
2890b57cec5SDimitry Andric  typedef _Tp value_type;
290*cb14a3feSDimitry Andric  static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
291*cb14a3feSDimitry Andric  union {
2920b57cec5SDimitry Andric    char __null_state_;
2930b57cec5SDimitry Andric    value_type __val_;
2940b57cec5SDimitry Andric  };
2950b57cec5SDimitry Andric  bool __engaged_;
2960b57cec5SDimitry Andric
297*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() {
2980b57cec5SDimitry Andric    if (__engaged_)
2990b57cec5SDimitry Andric      __val_.~value_type();
3000b57cec5SDimitry Andric  }
3010b57cec5SDimitry Andric
302*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric  template <class... _Args>
305*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
306*cb14a3feSDimitry Andric      : __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
3070b57cec5SDimitry Andric
30806c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
3090eae32dcSDimitry Andric  template <class _Fp, class... _Args>
310*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(
311*cb14a3feSDimitry Andric      __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3125f757f3fSDimitry Andric      : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
3130eae32dcSDimitry Andric#  endif
3140eae32dcSDimitry Andric
315*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
316*cb14a3feSDimitry Andric    if (__engaged_) {
3170b57cec5SDimitry Andric      __val_.~value_type();
3180b57cec5SDimitry Andric      __engaged_ = false;
3190b57cec5SDimitry Andric    }
3200b57cec5SDimitry Andric  }
3210b57cec5SDimitry Andric};
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andrictemplate <class _Tp>
324*cb14a3feSDimitry Andricstruct __optional_destruct_base<_Tp, true> {
3250b57cec5SDimitry Andric  typedef _Tp value_type;
326*cb14a3feSDimitry Andric  static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
327*cb14a3feSDimitry Andric  union {
3280b57cec5SDimitry Andric    char __null_state_;
3290b57cec5SDimitry Andric    value_type __val_;
3300b57cec5SDimitry Andric  };
3310b57cec5SDimitry Andric  bool __engaged_;
3320b57cec5SDimitry Andric
333*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric  template <class... _Args>
336*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
337*cb14a3feSDimitry Andric      : __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
3380b57cec5SDimitry Andric
33906c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
3400eae32dcSDimitry Andric  template <class _Fp, class... _Args>
341*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(
342*cb14a3feSDimitry Andric      __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
3435f757f3fSDimitry Andric      : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
3440eae32dcSDimitry Andric#  endif
3450eae32dcSDimitry Andric
346*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
347*cb14a3feSDimitry Andric    if (__engaged_) {
3480b57cec5SDimitry Andric      __engaged_ = false;
3490b57cec5SDimitry Andric    }
3500b57cec5SDimitry Andric  }
3510b57cec5SDimitry Andric};
3520b57cec5SDimitry Andric
3530b57cec5SDimitry Andrictemplate <class _Tp, bool = is_reference<_Tp>::value>
354*cb14a3feSDimitry Andricstruct __optional_storage_base : __optional_destruct_base<_Tp> {
3550b57cec5SDimitry Andric  using __base     = __optional_destruct_base<_Tp>;
3560b57cec5SDimitry Andric  using value_type = _Tp;
3570b57cec5SDimitry Andric  using __base::__base;
3580b57cec5SDimitry Andric
359*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; }
3600b57cec5SDimitry Andric
361*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; }
362*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; }
363*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); }
364*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); }
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric  template <class... _Args>
367*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) {
36806c3fb27SDimitry Andric    _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
3695f757f3fSDimitry Andric    std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...);
3700b57cec5SDimitry Andric    this->__engaged_ = true;
3710b57cec5SDimitry Andric  }
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric  template <class _That>
374*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
3750b57cec5SDimitry Andric    if (__opt.has_value())
3765f757f3fSDimitry Andric      __construct(std::forward<_That>(__opt).__get());
3770b57cec5SDimitry Andric  }
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andric  template <class _That>
380*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
381*cb14a3feSDimitry Andric    if (this->__engaged_ == __opt.has_value()) {
3820b57cec5SDimitry Andric      if (this->__engaged_)
3835f757f3fSDimitry Andric        this->__val_ = std::forward<_That>(__opt).__get();
384*cb14a3feSDimitry Andric    } else {
3850b57cec5SDimitry Andric      if (this->__engaged_)
3860b57cec5SDimitry Andric        this->reset();
3870b57cec5SDimitry Andric      else
3885f757f3fSDimitry Andric        __construct(std::forward<_That>(__opt).__get());
3890b57cec5SDimitry Andric    }
3900b57cec5SDimitry Andric  }
3910b57cec5SDimitry Andric};
3920b57cec5SDimitry Andric
39381ad6265SDimitry Andric// optional<T&> is currently required to be ill-formed. However, it may
39481ad6265SDimitry Andric// be allowed in the future. For this reason, it has already been implemented
39581ad6265SDimitry Andric// to ensure we can make the change in an ABI-compatible manner.
3960b57cec5SDimitry Andrictemplate <class _Tp>
397*cb14a3feSDimitry Andricstruct __optional_storage_base<_Tp, true> {
3980b57cec5SDimitry Andric  using value_type = _Tp;
3990b57cec5SDimitry Andric  using __raw_type = remove_reference_t<_Tp>;
4000b57cec5SDimitry Andric  __raw_type* __value_;
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric  template <class _Up>
40306c3fb27SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
404bdd1243dSDimitry Andric    using _RawUp = __libcpp_remove_reference_t<_Up>;
4050b57cec5SDimitry Andric    using _UpPtr = _RawUp*;
406bdd1243dSDimitry Andric    using _RawTp = __libcpp_remove_reference_t<_Tp>;
4070b57cec5SDimitry Andric    using _TpPtr = _RawTp*;
408*cb14a3feSDimitry Andric    using _CheckLValueArg =
409*cb14a3feSDimitry Andric        integral_constant<bool,
410*cb14a3feSDimitry Andric                          (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) ||
411*cb14a3feSDimitry Andric                              is_same<_RawUp, reference_wrapper<_RawTp>>::value ||
412*cb14a3feSDimitry Andric                              is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value >;
413*cb14a3feSDimitry Andric    return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) ||
414*cb14a3feSDimitry Andric           (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
4150b57cec5SDimitry Andric            is_convertible<_UpPtr, _TpPtr>::value);
4160b57cec5SDimitry Andric  }
4170b57cec5SDimitry Andric
418*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric  template <class _UArg>
421*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
422*cb14a3feSDimitry Andric      : __value_(std::addressof(__uarg)) {
4230b57cec5SDimitry Andric    static_assert(__can_bind_reference<_UArg>(),
4240b57cec5SDimitry Andric                  "Attempted to construct a reference element in tuple from a "
4250b57cec5SDimitry Andric                  "possible temporary");
4260b57cec5SDimitry Andric  }
4270b57cec5SDimitry Andric
428*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
4290b57cec5SDimitry Andric
430*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; }
4310b57cec5SDimitry Andric
432*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; }
4330b57cec5SDimitry Andric
434*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); }
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric  template <class _UArg>
437*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) {
43806c3fb27SDimitry Andric    _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
4390b57cec5SDimitry Andric    static_assert(__can_bind_reference<_UArg>(),
4400b57cec5SDimitry Andric                  "Attempted to construct a reference element in tuple from a "
4410b57cec5SDimitry Andric                  "possible temporary");
4425f757f3fSDimitry Andric    __value_ = std::addressof(__val);
4430b57cec5SDimitry Andric  }
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric  template <class _That>
446*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
4470b57cec5SDimitry Andric    if (__opt.has_value())
4485f757f3fSDimitry Andric      __construct(std::forward<_That>(__opt).__get());
4490b57cec5SDimitry Andric  }
4500b57cec5SDimitry Andric
4510b57cec5SDimitry Andric  template <class _That>
452*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
453*cb14a3feSDimitry Andric    if (has_value() == __opt.has_value()) {
4540b57cec5SDimitry Andric      if (has_value())
4555f757f3fSDimitry Andric        *__value_ = std::forward<_That>(__opt).__get();
456*cb14a3feSDimitry Andric    } else {
4570b57cec5SDimitry Andric      if (has_value())
4580b57cec5SDimitry Andric        reset();
4590b57cec5SDimitry Andric      else
4605f757f3fSDimitry Andric        __construct(std::forward<_That>(__opt).__get());
4610b57cec5SDimitry Andric    }
4620b57cec5SDimitry Andric  }
4630b57cec5SDimitry Andric};
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
466*cb14a3feSDimitry Andricstruct __optional_copy_base : __optional_storage_base<_Tp> {
4670b57cec5SDimitry Andric  using __optional_storage_base<_Tp>::__optional_storage_base;
4680b57cec5SDimitry Andric};
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andrictemplate <class _Tp>
471*cb14a3feSDimitry Andricstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> {
4720b57cec5SDimitry Andric  using __optional_storage_base<_Tp>::__optional_storage_base;
4730b57cec5SDimitry Andric
474*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default;
4750b57cec5SDimitry Andric
476*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) {
4770b57cec5SDimitry Andric    this->__construct_from(__opt);
4780b57cec5SDimitry Andric  }
4790b57cec5SDimitry Andric
480*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&)                 = default;
481*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default;
482*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&)      = default;
4830b57cec5SDimitry Andric};
4840b57cec5SDimitry Andric
4850b57cec5SDimitry Andrictemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
486*cb14a3feSDimitry Andricstruct __optional_move_base : __optional_copy_base<_Tp> {
4870b57cec5SDimitry Andric  using __optional_copy_base<_Tp>::__optional_copy_base;
4880b57cec5SDimitry Andric};
4890b57cec5SDimitry Andric
4900b57cec5SDimitry Andrictemplate <class _Tp>
491*cb14a3feSDimitry Andricstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> {
4920b57cec5SDimitry Andric  using value_type = _Tp;
4930b57cec5SDimitry Andric  using __optional_copy_base<_Tp>::__optional_copy_base;
4940b57cec5SDimitry Andric
495*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base()                            = default;
496*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default;
4970b57cec5SDimitry Andric
498*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
499*cb14a3feSDimitry Andric  __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) {
5005f757f3fSDimitry Andric    this->__construct_from(std::move(__opt));
5010b57cec5SDimitry Andric  }
5020b57cec5SDimitry Andric
503*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default;
504*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&)      = default;
5050b57cec5SDimitry Andric};
5060b57cec5SDimitry Andric
507*cb14a3feSDimitry Andrictemplate <class _Tp,
508*cb14a3feSDimitry Andric          bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value &&
5090b57cec5SDimitry Andric                 is_trivially_copy_assignable<_Tp>::value>
510*cb14a3feSDimitry Andricstruct __optional_copy_assign_base : __optional_move_base<_Tp> {
5110b57cec5SDimitry Andric  using __optional_move_base<_Tp>::__optional_move_base;
5120b57cec5SDimitry Andric};
5130b57cec5SDimitry Andric
5140b57cec5SDimitry Andrictemplate <class _Tp>
515*cb14a3feSDimitry Andricstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> {
5160b57cec5SDimitry Andric  using __optional_move_base<_Tp>::__optional_move_base;
5170b57cec5SDimitry Andric
518*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base()                                   = default;
519*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
520*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&)      = default;
5210b57cec5SDimitry Andric
522*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base&
523*cb14a3feSDimitry Andric  operator=(const __optional_copy_assign_base& __opt) {
5240b57cec5SDimitry Andric    this->__assign_from(__opt);
5250b57cec5SDimitry Andric    return *this;
5260b57cec5SDimitry Andric  }
5270b57cec5SDimitry Andric
528*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
5290b57cec5SDimitry Andric};
5300b57cec5SDimitry Andric
531*cb14a3feSDimitry Andrictemplate <class _Tp,
532*cb14a3feSDimitry Andric          bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value &&
5330b57cec5SDimitry Andric                 is_trivially_move_assignable<_Tp>::value>
534*cb14a3feSDimitry Andricstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
5350b57cec5SDimitry Andric  using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
5360b57cec5SDimitry Andric};
5370b57cec5SDimitry Andric
5380b57cec5SDimitry Andrictemplate <class _Tp>
539*cb14a3feSDimitry Andricstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> {
5400b57cec5SDimitry Andric  using value_type = _Tp;
5410b57cec5SDimitry Andric  using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
5420b57cec5SDimitry Andric
543*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base()                                              = default;
544*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt)      = default;
545*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&)                 = default;
546*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
5470b57cec5SDimitry Andric
548*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base&
549*cb14a3feSDimitry Andric  operator=(__optional_move_assign_base&& __opt) noexcept(
550*cb14a3feSDimitry Andric      is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) {
5515f757f3fSDimitry Andric    this->__assign_from(std::move(__opt));
5520b57cec5SDimitry Andric    return *this;
5530b57cec5SDimitry Andric  }
5540b57cec5SDimitry Andric};
5550b57cec5SDimitry Andric
5560b57cec5SDimitry Andrictemplate <class _Tp>
557*cb14a3feSDimitry Andricusing __optional_sfinae_ctor_base_t =
558*cb14a3feSDimitry Andric    __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >;
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andrictemplate <class _Tp>
561*cb14a3feSDimitry Andricusing __optional_sfinae_assign_base_t =
562*cb14a3feSDimitry Andric    __sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
563*cb14a3feSDimitry Andric                          (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >;
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andrictemplate <class _Tp>
5660eae32dcSDimitry Andricclass optional;
56706c3fb27SDimitry Andric
56806c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 20
56906c3fb27SDimitry Andric
57006c3fb27SDimitry Andrictemplate <class _Tp>
57106c3fb27SDimitry Andricconcept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); };
57206c3fb27SDimitry Andric
57306c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
57406c3fb27SDimitry Andric
5750eae32dcSDimitry Andrictemplate <class _Tp>
5760eae32dcSDimitry Andricstruct __is_std_optional : false_type {};
577*cb14a3feSDimitry Andrictemplate <class _Tp>
578*cb14a3feSDimitry Andricstruct __is_std_optional<optional<_Tp>> : true_type {};
5790eae32dcSDimitry Andric
5800eae32dcSDimitry Andrictemplate <class _Tp>
58106c3fb27SDimitry Andricclass _LIBCPP_DECLSPEC_EMPTY_BASES optional
582*cb14a3feSDimitry Andric    : private __optional_move_assign_base<_Tp>,
583*cb14a3feSDimitry Andric      private __optional_sfinae_ctor_base_t<_Tp>,
584*cb14a3feSDimitry Andric      private __optional_sfinae_assign_base_t<_Tp> {
5850b57cec5SDimitry Andric  using __base = __optional_move_assign_base<_Tp>;
586*cb14a3feSDimitry Andric
5870b57cec5SDimitry Andricpublic:
5880b57cec5SDimitry Andric  using value_type = _Tp;
5890b57cec5SDimitry Andric
5900b57cec5SDimitry Andricprivate:
5910b57cec5SDimitry Andric  // Disable the reference extension using this static assert.
592bdd1243dSDimitry Andric  static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,
5930b57cec5SDimitry Andric                "instantiation of optional with in_place_t is ill-formed");
594bdd1243dSDimitry Andric  static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>,
5950b57cec5SDimitry Andric                "instantiation of optional with nullopt_t is ill-formed");
596*cb14a3feSDimitry Andric  static_assert(!is_reference_v<value_type>, "instantiation of optional with a reference type is ill-formed");
597*cb14a3feSDimitry Andric  static_assert(is_destructible_v<value_type>, "instantiation of optional with a non-destructible type is ill-formed");
598*cb14a3feSDimitry Andric  static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed");
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric  // LWG2756: conditionally explicit conversion from _Up
6010b57cec5SDimitry Andric  struct _CheckOptionalArgsConstructor {
6020b57cec5SDimitry Andric    template <class _Up>
60306c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
604*cb14a3feSDimitry Andric      return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
6050b57cec5SDimitry Andric    }
6060b57cec5SDimitry Andric
6070b57cec5SDimitry Andric    template <class _Up>
60806c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
609*cb14a3feSDimitry Andric      return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
6100b57cec5SDimitry Andric    }
6110b57cec5SDimitry Andric  };
6120b57cec5SDimitry Andric  template <class _Up>
613*cb14a3feSDimitry Andric  using _CheckOptionalArgsCtor =
614*cb14a3feSDimitry Andric      _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
6155f757f3fSDimitry Andric               (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value),
6160b57cec5SDimitry Andric           _CheckOptionalArgsConstructor,
617*cb14a3feSDimitry Andric           __check_tuple_constructor_fail >;
6180b57cec5SDimitry Andric  template <class _QualUp>
6190b57cec5SDimitry Andric  struct _CheckOptionalLikeConstructor {
6200b57cec5SDimitry Andric    template <class _Up, class _Opt = optional<_Up>>
621*cb14a3feSDimitry Andric    using __check_constructible_from_opt =
622*cb14a3feSDimitry Andric        _Or< is_constructible<_Tp, _Opt&>,
6230b57cec5SDimitry Andric             is_constructible<_Tp, _Opt const&>,
6240b57cec5SDimitry Andric             is_constructible<_Tp, _Opt&&>,
6250b57cec5SDimitry Andric             is_constructible<_Tp, _Opt const&&>,
6260b57cec5SDimitry Andric             is_convertible<_Opt&, _Tp>,
6270b57cec5SDimitry Andric             is_convertible<_Opt const&, _Tp>,
6280b57cec5SDimitry Andric             is_convertible<_Opt&&, _Tp>,
629*cb14a3feSDimitry Andric             is_convertible<_Opt const&&, _Tp> >;
6300b57cec5SDimitry Andric    template <class _Up, class _Opt = optional<_Up>>
631*cb14a3feSDimitry Andric    using __check_assignable_from_opt =
632*cb14a3feSDimitry Andric        _Or< is_assignable<_Tp&, _Opt&>,
6330b57cec5SDimitry Andric             is_assignable<_Tp&, _Opt const&>,
6340b57cec5SDimitry Andric             is_assignable<_Tp&, _Opt&&>,
635*cb14a3feSDimitry Andric             is_assignable<_Tp&, _Opt const&&> >;
6360b57cec5SDimitry Andric    template <class _Up, class _QUp = _QualUp>
63706c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
6380b57cec5SDimitry Andric      return is_convertible<_QUp, _Tp>::value &&
6395f757f3fSDimitry Andric             (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
6400b57cec5SDimitry Andric    }
6410b57cec5SDimitry Andric    template <class _Up, class _QUp = _QualUp>
64206c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
6430b57cec5SDimitry Andric      return !is_convertible<_QUp, _Tp>::value &&
6445f757f3fSDimitry Andric             (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
6450b57cec5SDimitry Andric    }
6460b57cec5SDimitry Andric    template <class _Up, class _QUp = _QualUp>
64706c3fb27SDimitry Andric    _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
648e8d8bef9SDimitry Andric      // Construction and assignability of _QUp to _Tp has already been
6490b57cec5SDimitry Andric      // checked.
650*cb14a3feSDimitry Andric      return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value;
6510b57cec5SDimitry Andric    }
6520b57cec5SDimitry Andric  };
6530b57cec5SDimitry Andric
6540b57cec5SDimitry Andric  template <class _Up, class _QualUp>
655*cb14a3feSDimitry Andric  using _CheckOptionalLikeCtor =
656*cb14a3feSDimitry Andric      _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
6570b57cec5SDimitry Andric           _CheckOptionalLikeConstructor<_QualUp>,
658*cb14a3feSDimitry Andric           __check_tuple_constructor_fail >;
6590b57cec5SDimitry Andric  template <class _Up, class _QualUp>
660*cb14a3feSDimitry Andric  using _CheckOptionalLikeAssign =
661*cb14a3feSDimitry Andric      _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,
6620b57cec5SDimitry Andric           _CheckOptionalLikeConstructor<_QualUp>,
663*cb14a3feSDimitry Andric           __check_tuple_constructor_fail >;
6640eae32dcSDimitry Andric
6650b57cec5SDimitry Andricpublic:
6665f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
6675f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default;
6685f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&)      = default;
6695f757f3fSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {}
6700b57cec5SDimitry Andric
671*cb14a3feSDimitry Andric  template <
672*cb14a3feSDimitry Andric      class _InPlaceT,
673*cb14a3feSDimitry Andric      class... _Args,
674*cb14a3feSDimitry Andric      class = enable_if_t< _And< _IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...> >::value > >
675*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
6765f757f3fSDimitry Andric      : __base(in_place, std::forward<_Args>(__args)...) {}
6770b57cec5SDimitry Andric
678*cb14a3feSDimitry Andric  template <class _Up,
679*cb14a3feSDimitry Andric            class... _Args,
680*cb14a3feSDimitry Andric            class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> >
681*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
6825f757f3fSDimitry Andric      : __base(in_place, __il, std::forward<_Args>(__args)...) {}
6830b57cec5SDimitry Andric
684*cb14a3feSDimitry Andric  template <class _Up                                                                         = value_type,
685*cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
686*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
6870b57cec5SDimitry Andric
688*cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
689*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric  // LWG2756: conditionally explicit conversion from const optional<_Up>&
692*cb14a3feSDimitry Andric  template <class _Up,
693*cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
694*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
6950b57cec5SDimitry Andric    this->__construct_from(__v);
6960b57cec5SDimitry Andric  }
697*cb14a3feSDimitry Andric  template <class _Up,
698*cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
699*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
7000b57cec5SDimitry Andric    this->__construct_from(__v);
7010b57cec5SDimitry Andric  }
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric  // LWG2756: conditionally explicit conversion from optional<_Up>&&
704*cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
705*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
7065f757f3fSDimitry Andric    this->__construct_from(std::move(__v));
7070b57cec5SDimitry Andric  }
708*cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
709*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
7105f757f3fSDimitry Andric    this->__construct_from(std::move(__v));
7110b57cec5SDimitry Andric  }
7120b57cec5SDimitry Andric
71306c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
7140eae32dcSDimitry Andric  template <class _Fp, class... _Args>
715*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
716*cb14a3feSDimitry Andric      : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
7170eae32dcSDimitry Andric#  endif
7180eae32dcSDimitry Andric
719*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept {
7200b57cec5SDimitry Andric    reset();
7210b57cec5SDimitry Andric    return *this;
7220b57cec5SDimitry Andric  }
7230b57cec5SDimitry Andric
72406c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
72506c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&)      = default;
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric  // LWG2756
728*cb14a3feSDimitry Andric  template <
729*cb14a3feSDimitry Andric      class _Up = value_type,
730*cb14a3feSDimitry Andric      class     = enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Up>, optional>,
731*cb14a3feSDimitry Andric                                 _Or< _IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>> >,
7320b57cec5SDimitry Andric                                 is_constructible<value_type, _Up>,
733*cb14a3feSDimitry Andric                                 is_assignable<value_type&, _Up> >::value> >
734*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
7350b57cec5SDimitry Andric    if (this->has_value())
7365f757f3fSDimitry Andric      this->__get() = std::forward<_Up>(__v);
7370b57cec5SDimitry Andric    else
7385f757f3fSDimitry Andric      this->__construct(std::forward<_Up>(__v));
7390b57cec5SDimitry Andric    return *this;
7400b57cec5SDimitry Andric  }
7410b57cec5SDimitry Andric
7420b57cec5SDimitry Andric  // LWG2756
743*cb14a3feSDimitry Andric  template <class _Up,
744*cb14a3feSDimitry Andric            enable_if_t< _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
745*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
7460b57cec5SDimitry Andric    this->__assign_from(__v);
7470b57cec5SDimitry Andric    return *this;
7480b57cec5SDimitry Andric  }
7490b57cec5SDimitry Andric
7500b57cec5SDimitry Andric  // LWG2756
751*cb14a3feSDimitry Andric  template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
752*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
7535f757f3fSDimitry Andric    this->__assign_from(std::move(__v));
7540b57cec5SDimitry Andric    return *this;
7550b57cec5SDimitry Andric  }
7560b57cec5SDimitry Andric
757*cb14a3feSDimitry Andric  template <class... _Args, class = enable_if_t< is_constructible_v<value_type, _Args...> > >
758*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
7590b57cec5SDimitry Andric    reset();
7605f757f3fSDimitry Andric    this->__construct(std::forward<_Args>(__args)...);
7610b57cec5SDimitry Andric    return this->__get();
7620b57cec5SDimitry Andric  }
7630b57cec5SDimitry Andric
764*cb14a3feSDimitry Andric  template <class _Up,
765*cb14a3feSDimitry Andric            class... _Args,
766*cb14a3feSDimitry Andric            class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...> > >
767*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
7680b57cec5SDimitry Andric    reset();
7695f757f3fSDimitry Andric    this->__construct(__il, std::forward<_Args>(__args)...);
7700b57cec5SDimitry Andric    return this->__get();
7710b57cec5SDimitry Andric  }
7720b57cec5SDimitry Andric
773*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
774*cb14a3feSDimitry Andric  swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<value_type> && is_nothrow_swappable_v<value_type>) {
775*cb14a3feSDimitry Andric    if (this->has_value() == __opt.has_value()) {
7765f757f3fSDimitry Andric      using std::swap;
7770b57cec5SDimitry Andric      if (this->has_value())
7780b57cec5SDimitry Andric        swap(this->__get(), __opt.__get());
779*cb14a3feSDimitry Andric    } else {
780*cb14a3feSDimitry Andric      if (this->has_value()) {
7815f757f3fSDimitry Andric        __opt.__construct(std::move(this->__get()));
7820b57cec5SDimitry Andric        reset();
783*cb14a3feSDimitry Andric      } else {
7845f757f3fSDimitry Andric        this->__construct(std::move(__opt.__get()));
7850b57cec5SDimitry Andric        __opt.reset();
7860b57cec5SDimitry Andric      }
7870b57cec5SDimitry Andric    }
7880b57cec5SDimitry Andric  }
7890b57cec5SDimitry Andric
790*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const {
79106c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
7925f757f3fSDimitry Andric    return std::addressof(this->__get());
7930b57cec5SDimitry Andric  }
7940b57cec5SDimitry Andric
795*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() {
79606c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
7975f757f3fSDimitry Andric    return std::addressof(this->__get());
7980b57cec5SDimitry Andric  }
7990b57cec5SDimitry Andric
800*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept {
80106c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8020b57cec5SDimitry Andric    return this->__get();
8030b57cec5SDimitry Andric  }
8040b57cec5SDimitry Andric
805*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept {
80606c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8070b57cec5SDimitry Andric    return this->__get();
8080b57cec5SDimitry Andric  }
8090b57cec5SDimitry Andric
810*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept {
81106c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8125f757f3fSDimitry Andric    return std::move(this->__get());
8130b57cec5SDimitry Andric  }
8140b57cec5SDimitry Andric
815*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept {
81606c3fb27SDimitry Andric    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
8175f757f3fSDimitry Andric    return std::move(this->__get());
8180b57cec5SDimitry Andric  }
8190b57cec5SDimitry Andric
820*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); }
8210b57cec5SDimitry Andric
8220b57cec5SDimitry Andric  using __base::__get;
823*cb14a3feSDimitry Andric  using __base::has_value;
8240b57cec5SDimitry Andric
825*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const& value() const& {
8260b57cec5SDimitry Andric    if (!this->has_value())
8270b57cec5SDimitry Andric      __throw_bad_optional_access();
8280b57cec5SDimitry Andric    return this->__get();
8290b57cec5SDimitry Andric  }
8300b57cec5SDimitry Andric
831*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& value() & {
8320b57cec5SDimitry Andric    if (!this->has_value())
8330b57cec5SDimitry Andric      __throw_bad_optional_access();
8340b57cec5SDimitry Andric    return this->__get();
8350b57cec5SDimitry Andric  }
8360b57cec5SDimitry Andric
837*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& value() && {
8380b57cec5SDimitry Andric    if (!this->has_value())
8390b57cec5SDimitry Andric      __throw_bad_optional_access();
8405f757f3fSDimitry Andric    return std::move(this->__get());
8410b57cec5SDimitry Andric  }
8420b57cec5SDimitry Andric
843*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type const&& value() const&& {
8440b57cec5SDimitry Andric    if (!this->has_value())
8450b57cec5SDimitry Andric      __throw_bad_optional_access();
8465f757f3fSDimitry Andric    return std::move(this->__get());
8470b57cec5SDimitry Andric  }
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric  template <class _Up>
850*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) const& {
851*cb14a3feSDimitry Andric    static_assert(is_copy_constructible_v<value_type>, "optional<T>::value_or: T must be copy constructible");
852*cb14a3feSDimitry Andric    static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T");
853*cb14a3feSDimitry Andric    return this->has_value() ? this->__get() : static_cast<value_type>(std::forward<_Up>(__v));
8540b57cec5SDimitry Andric  }
8550b57cec5SDimitry Andric
8560b57cec5SDimitry Andric  template <class _Up>
857*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) && {
858*cb14a3feSDimitry Andric    static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible");
859*cb14a3feSDimitry Andric    static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T");
860*cb14a3feSDimitry Andric    return this->has_value() ? std::move(this->__get()) : static_cast<value_type>(std::forward<_Up>(__v));
8610b57cec5SDimitry Andric  }
8620b57cec5SDimitry Andric
86306c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 23
8640eae32dcSDimitry Andric  template <class _Func>
865*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) & {
8660eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&>;
8670eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8680eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
8690eae32dcSDimitry Andric    if (*this)
8705f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), value());
8710eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
8720eae32dcSDimitry Andric  }
8730eae32dcSDimitry Andric
8740eae32dcSDimitry Andric  template <class _Func>
875*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) const& {
8760eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&>;
8770eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8780eae32dcSDimitry Andric                  "Result of f(value()) must be a specialization of std::optional");
8790eae32dcSDimitry Andric    if (*this)
8805f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), value());
8810eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
8820eae32dcSDimitry Andric  }
8830eae32dcSDimitry Andric
8840eae32dcSDimitry Andric  template <class _Func>
885*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) && {
8860eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, value_type&&>;
8870eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8880eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
8890eae32dcSDimitry Andric    if (*this)
8905f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), std::move(value()));
8910eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
8920eae32dcSDimitry Andric  }
8930eae32dcSDimitry Andric
8940eae32dcSDimitry Andric  template <class _Func>
895*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
8960eae32dcSDimitry Andric    using _Up = invoke_result_t<_Func, const value_type&&>;
8970eae32dcSDimitry Andric    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
8980eae32dcSDimitry Andric                  "Result of f(std::move(value())) must be a specialization of std::optional");
8990eae32dcSDimitry Andric    if (*this)
9005f757f3fSDimitry Andric      return std::invoke(std::forward<_Func>(__f), std::move(value()));
9010eae32dcSDimitry Andric    return remove_cvref_t<_Up>();
9020eae32dcSDimitry Andric  }
9030eae32dcSDimitry Andric
9040eae32dcSDimitry Andric  template <class _Func>
905*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) & {
9060eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
9070eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
908*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
909*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
9100eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
9110eae32dcSDimitry Andric    if (*this)
9125f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
9130eae32dcSDimitry Andric    return optional<_Up>();
9140eae32dcSDimitry Andric  }
9150eae32dcSDimitry Andric
9160eae32dcSDimitry Andric  template <class _Func>
917*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const& {
9180eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
9190eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
920*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
921*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
9220eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
9230eae32dcSDimitry Andric    if (*this)
9245f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
9250eae32dcSDimitry Andric    return optional<_Up>();
9260eae32dcSDimitry Andric  }
9270eae32dcSDimitry Andric
9280eae32dcSDimitry Andric  template <class _Func>
929*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) && {
9300eae32dcSDimitry Andric    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
9310eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
932*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
933*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
9340eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
9350eae32dcSDimitry Andric    if (*this)
9365f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
9370eae32dcSDimitry Andric    return optional<_Up>();
9380eae32dcSDimitry Andric  }
9390eae32dcSDimitry Andric
9400eae32dcSDimitry Andric  template <class _Func>
941*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto transform(_Func&& __f) const&& {
9420eae32dcSDimitry Andric    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
9430eae32dcSDimitry Andric    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
944*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
945*cb14a3feSDimitry Andric    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
9460eae32dcSDimitry Andric    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
9470eae32dcSDimitry Andric    if (*this)
9485f757f3fSDimitry Andric      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
9490eae32dcSDimitry Andric    return optional<_Up>();
9500eae32dcSDimitry Andric  }
9510eae32dcSDimitry Andric
9520eae32dcSDimitry Andric  template <invocable _Func>
953*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
954*cb14a3feSDimitry Andric    requires is_copy_constructible_v<value_type>
955*cb14a3feSDimitry Andric  {
9560eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
9570eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
9580eae32dcSDimitry Andric    if (*this)
9590eae32dcSDimitry Andric      return *this;
9605f757f3fSDimitry Andric    return std::forward<_Func>(__f)();
9610eae32dcSDimitry Andric  }
9620eae32dcSDimitry Andric
9630eae32dcSDimitry Andric  template <invocable _Func>
964*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
965*cb14a3feSDimitry Andric    requires is_move_constructible_v<value_type>
966*cb14a3feSDimitry Andric  {
9670eae32dcSDimitry Andric    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
9680eae32dcSDimitry Andric                  "Result of f() should be the same type as this optional");
9690eae32dcSDimitry Andric    if (*this)
9705f757f3fSDimitry Andric      return std::move(*this);
9715f757f3fSDimitry Andric    return std::forward<_Func>(__f)();
9720eae32dcSDimitry Andric  }
97306c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 23
9740eae32dcSDimitry Andric
9750b57cec5SDimitry Andric  using __base::reset;
9760b57cec5SDimitry Andric};
9770b57cec5SDimitry Andric
978349cc55cSDimitry Andric#  if _LIBCPP_STD_VER >= 17
97904eeddc0SDimitry Andrictemplate <class _Tp>
98004eeddc0SDimitry Andricoptional(_Tp) -> optional<_Tp>;
9810b57cec5SDimitry Andric#  endif
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric// Comparisons between optionals
9840b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
985*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
986*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
987*cb14a3feSDimitry Andric    bool >
988*cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const optional<_Up>& __y) {
9890b57cec5SDimitry Andric  if (static_cast<bool>(__x) != static_cast<bool>(__y))
9900b57cec5SDimitry Andric    return false;
9910b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
9920b57cec5SDimitry Andric    return true;
9930b57cec5SDimitry Andric  return *__x == *__y;
9940b57cec5SDimitry Andric}
9950b57cec5SDimitry Andric
9960b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
997*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
998*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
999*cb14a3feSDimitry Andric    bool >
1000*cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const optional<_Up>& __y) {
10010b57cec5SDimitry Andric  if (static_cast<bool>(__x) != static_cast<bool>(__y))
10020b57cec5SDimitry Andric    return true;
10030b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10040b57cec5SDimitry Andric    return false;
10050b57cec5SDimitry Andric  return *__x != *__y;
10060b57cec5SDimitry Andric}
10070b57cec5SDimitry Andric
10080b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1009*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1010*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
1011*cb14a3feSDimitry Andric    bool >
1012*cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const optional<_Up>& __y) {
10130b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10140b57cec5SDimitry Andric    return false;
10150b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10160b57cec5SDimitry Andric    return true;
10170b57cec5SDimitry Andric  return *__x < *__y;
10180b57cec5SDimitry Andric}
10190b57cec5SDimitry Andric
10200b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1021*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1022*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
1023*cb14a3feSDimitry Andric    bool >
1024*cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const optional<_Up>& __y) {
10250b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10260b57cec5SDimitry Andric    return false;
10270b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10280b57cec5SDimitry Andric    return true;
10290b57cec5SDimitry Andric  return *__x > *__y;
10300b57cec5SDimitry Andric}
10310b57cec5SDimitry Andric
10320b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1033*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1034*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
1035*cb14a3feSDimitry Andric    bool >
1036*cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const optional<_Up>& __y) {
10370b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10380b57cec5SDimitry Andric    return true;
10390b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10400b57cec5SDimitry Andric    return false;
10410b57cec5SDimitry Andric  return *__x <= *__y;
10420b57cec5SDimitry Andric}
10430b57cec5SDimitry Andric
10440b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1045*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1046*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
1047*cb14a3feSDimitry Andric    bool >
1048*cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const optional<_Up>& __y) {
10490b57cec5SDimitry Andric  if (!static_cast<bool>(__y))
10500b57cec5SDimitry Andric    return true;
10510b57cec5SDimitry Andric  if (!static_cast<bool>(__x))
10520b57cec5SDimitry Andric    return false;
10530b57cec5SDimitry Andric  return *__x >= *__y;
10540b57cec5SDimitry Andric}
10550b57cec5SDimitry Andric
105606c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 20
105706c3fb27SDimitry Andric
105806c3fb27SDimitry Andrictemplate <class _Tp, three_way_comparable_with<_Tp> _Up>
105906c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
106006c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) {
106106c3fb27SDimitry Andric  if (__x && __y)
106206c3fb27SDimitry Andric    return *__x <=> *__y;
106306c3fb27SDimitry Andric  return __x.has_value() <=> __y.has_value();
106406c3fb27SDimitry Andric}
106506c3fb27SDimitry Andric
106606c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
106706c3fb27SDimitry Andric
10680b57cec5SDimitry Andric// Comparisons with nullopt
10690b57cec5SDimitry Andrictemplate <class _Tp>
1070*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept {
10710b57cec5SDimitry Andric  return !static_cast<bool>(__x);
10720b57cec5SDimitry Andric}
10730b57cec5SDimitry Andric
107406c3fb27SDimitry Andric#  if _LIBCPP_STD_VER <= 17
107506c3fb27SDimitry Andric
10760b57cec5SDimitry Andrictemplate <class _Tp>
1077*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept {
10780b57cec5SDimitry Andric  return !static_cast<bool>(__x);
10790b57cec5SDimitry Andric}
10800b57cec5SDimitry Andric
10810b57cec5SDimitry Andrictemplate <class _Tp>
1082*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept {
10830b57cec5SDimitry Andric  return static_cast<bool>(__x);
10840b57cec5SDimitry Andric}
10850b57cec5SDimitry Andric
10860b57cec5SDimitry Andrictemplate <class _Tp>
1087*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept {
10880b57cec5SDimitry Andric  return static_cast<bool>(__x);
10890b57cec5SDimitry Andric}
10900b57cec5SDimitry Andric
10910b57cec5SDimitry Andrictemplate <class _Tp>
1092*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept {
10930b57cec5SDimitry Andric  return false;
10940b57cec5SDimitry Andric}
10950b57cec5SDimitry Andric
10960b57cec5SDimitry Andrictemplate <class _Tp>
1097*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept {
10980b57cec5SDimitry Andric  return static_cast<bool>(__x);
10990b57cec5SDimitry Andric}
11000b57cec5SDimitry Andric
11010b57cec5SDimitry Andrictemplate <class _Tp>
1102*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept {
11030b57cec5SDimitry Andric  return !static_cast<bool>(__x);
11040b57cec5SDimitry Andric}
11050b57cec5SDimitry Andric
11060b57cec5SDimitry Andrictemplate <class _Tp>
1107*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept {
11080b57cec5SDimitry Andric  return true;
11090b57cec5SDimitry Andric}
11100b57cec5SDimitry Andric
11110b57cec5SDimitry Andrictemplate <class _Tp>
1112*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept {
11130b57cec5SDimitry Andric  return static_cast<bool>(__x);
11140b57cec5SDimitry Andric}
11150b57cec5SDimitry Andric
11160b57cec5SDimitry Andrictemplate <class _Tp>
1117*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept {
11180b57cec5SDimitry Andric  return false;
11190b57cec5SDimitry Andric}
11200b57cec5SDimitry Andric
11210b57cec5SDimitry Andrictemplate <class _Tp>
1122*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept {
11230b57cec5SDimitry Andric  return true;
11240b57cec5SDimitry Andric}
11250b57cec5SDimitry Andric
11260b57cec5SDimitry Andrictemplate <class _Tp>
1127*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept {
11280b57cec5SDimitry Andric  return !static_cast<bool>(__x);
11290b57cec5SDimitry Andric}
11300b57cec5SDimitry Andric
113106c3fb27SDimitry Andric#  else // _LIBCPP_STD_VER <= 17
113206c3fb27SDimitry Andric
113306c3fb27SDimitry Andrictemplate <class _Tp>
113406c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept {
113506c3fb27SDimitry Andric  return __x.has_value() <=> false;
113606c3fb27SDimitry Andric}
113706c3fb27SDimitry Andric
113806c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER <= 17
113906c3fb27SDimitry Andric
11400b57cec5SDimitry Andric// Comparisons with T
11410b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1142*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1143*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
1144*cb14a3feSDimitry Andric    bool >
1145*cb14a3feSDimitry Andricoperator==(const optional<_Tp>& __x, const _Up& __v) {
11460b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x == __v : false;
11470b57cec5SDimitry Andric}
11480b57cec5SDimitry Andric
11490b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1150*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1151*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
1152*cb14a3feSDimitry Andric    bool >
1153*cb14a3feSDimitry Andricoperator==(const _Tp& __v, const optional<_Up>& __x) {
11540b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v == *__x : false;
11550b57cec5SDimitry Andric}
11560b57cec5SDimitry Andric
11570b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1158*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1159*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
1160*cb14a3feSDimitry Andric    bool >
1161*cb14a3feSDimitry Andricoperator!=(const optional<_Tp>& __x, const _Up& __v) {
11620b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x != __v : true;
11630b57cec5SDimitry Andric}
11640b57cec5SDimitry Andric
11650b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1166*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1167*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
1168*cb14a3feSDimitry Andric    bool >
1169*cb14a3feSDimitry Andricoperator!=(const _Tp& __v, const optional<_Up>& __x) {
11700b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v != *__x : true;
11710b57cec5SDimitry Andric}
11720b57cec5SDimitry Andric
11730b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1174*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1175*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
1176*cb14a3feSDimitry Andric    bool >
1177*cb14a3feSDimitry Andricoperator<(const optional<_Tp>& __x, const _Up& __v) {
11780b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x < __v : true;
11790b57cec5SDimitry Andric}
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1182*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1183*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
1184*cb14a3feSDimitry Andric    bool >
1185*cb14a3feSDimitry Andricoperator<(const _Tp& __v, const optional<_Up>& __x) {
11860b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v < *__x : false;
11870b57cec5SDimitry Andric}
11880b57cec5SDimitry Andric
11890b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1190*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1191*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
1192*cb14a3feSDimitry Andric    bool >
1193*cb14a3feSDimitry Andricoperator<=(const optional<_Tp>& __x, const _Up& __v) {
11940b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x <= __v : true;
11950b57cec5SDimitry Andric}
11960b57cec5SDimitry Andric
11970b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1198*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1199*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
1200*cb14a3feSDimitry Andric    bool >
1201*cb14a3feSDimitry Andricoperator<=(const _Tp& __v, const optional<_Up>& __x) {
12020b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v <= *__x : false;
12030b57cec5SDimitry Andric}
12040b57cec5SDimitry Andric
12050b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1206*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1207*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
1208*cb14a3feSDimitry Andric    bool >
1209*cb14a3feSDimitry Andricoperator>(const optional<_Tp>& __x, const _Up& __v) {
12100b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x > __v : false;
12110b57cec5SDimitry Andric}
12120b57cec5SDimitry Andric
12130b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1214*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1215*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
1216*cb14a3feSDimitry Andric    bool >
1217*cb14a3feSDimitry Andricoperator>(const _Tp& __v, const optional<_Up>& __x) {
12180b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v > *__x : true;
12190b57cec5SDimitry Andric}
12200b57cec5SDimitry Andric
12210b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1222*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1223*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
1224*cb14a3feSDimitry Andric    bool >
1225*cb14a3feSDimitry Andricoperator>=(const optional<_Tp>& __x, const _Up& __v) {
12260b57cec5SDimitry Andric  return static_cast<bool>(__x) ? *__x >= __v : false;
12270b57cec5SDimitry Andric}
12280b57cec5SDimitry Andric
12290b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
1230*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
1231*cb14a3feSDimitry Andric    is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
1232*cb14a3feSDimitry Andric    bool >
1233*cb14a3feSDimitry Andricoperator>=(const _Tp& __v, const optional<_Up>& __x) {
12340b57cec5SDimitry Andric  return static_cast<bool>(__x) ? __v >= *__x : true;
12350b57cec5SDimitry Andric}
12360b57cec5SDimitry Andric
123706c3fb27SDimitry Andric#  if _LIBCPP_STD_VER >= 20
123806c3fb27SDimitry Andric
123906c3fb27SDimitry Andrictemplate <class _Tp, class _Up>
124006c3fb27SDimitry Andric  requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up>
124106c3fb27SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up>
124206c3fb27SDimitry Andricoperator<=>(const optional<_Tp>& __x, const _Up& __v) {
124306c3fb27SDimitry Andric  return __x.has_value() ? *__x <=> __v : strong_ordering::less;
124406c3fb27SDimitry Andric}
124506c3fb27SDimitry Andric
124606c3fb27SDimitry Andric#  endif // _LIBCPP_STD_VER >= 20
124706c3fb27SDimitry Andric
12480b57cec5SDimitry Andrictemplate <class _Tp>
12495f757f3fSDimitry Andricinline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
1250*cb14a3feSDimitry Andric    enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void >
1251*cb14a3feSDimitry Andric    swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) {
12520b57cec5SDimitry Andric  __x.swap(__y);
12530b57cec5SDimitry Andric}
12540b57cec5SDimitry Andric
12550b57cec5SDimitry Andrictemplate <class _Tp>
1256*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<decay_t<_Tp>> make_optional(_Tp&& __v) {
12575f757f3fSDimitry Andric  return optional<decay_t<_Tp>>(std::forward<_Tp>(__v));
12580b57cec5SDimitry Andric}
12590b57cec5SDimitry Andric
12600b57cec5SDimitry Andrictemplate <class _Tp, class... _Args>
1261*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(_Args&&... __args) {
12625f757f3fSDimitry Andric  return optional<_Tp>(in_place, std::forward<_Args>(__args)...);
12630b57cec5SDimitry Andric}
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args>
1266*cb14a3feSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) {
12675f757f3fSDimitry Andric  return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...);
12680b57cec5SDimitry Andric}
12690b57cec5SDimitry Andric
12700b57cec5SDimitry Andrictemplate <class _Tp>
1271*cb14a3feSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > {
1272fe6060f1SDimitry Andric#  if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1273fe6060f1SDimitry Andric  _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1274fe6060f1SDimitry Andric  _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
1275fe6060f1SDimitry Andric#  endif
12760b57cec5SDimitry Andric
1277*cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const {
12780b57cec5SDimitry Andric    return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
12790b57cec5SDimitry Andric  }
12800b57cec5SDimitry Andric};
12810b57cec5SDimitry Andric
12820b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
12830b57cec5SDimitry Andric
128406c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 17
128506c3fb27SDimitry Andric
128606c3fb27SDimitry Andric_LIBCPP_POP_MACROS
12870b57cec5SDimitry Andric
1288bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
1289bdd1243dSDimitry Andric#  include <atomic>
1290bdd1243dSDimitry Andric#  include <climits>
1291bdd1243dSDimitry Andric#  include <concepts>
1292bdd1243dSDimitry Andric#  include <ctime>
1293bdd1243dSDimitry Andric#  include <iterator>
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