1a9e65961SEric Fiselier// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
3a9e65961SEric Fiselier//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7a9e65961SEric Fiselier//
8a9e65961SEric Fiselier//===----------------------------------------------------------------------===//
9a9e65961SEric Fiselier
10a9e65961SEric Fiselier#ifndef _LIBCPP_OPTIONAL
11a9e65961SEric Fiselier#define _LIBCPP_OPTIONAL
12a9e65961SEric Fiselier
13a9e65961SEric Fiselier/*
14a9e65961SEric Fiselier    optional synopsis
15a9e65961SEric Fiselier
16a9e65961SEric Fiselier// C++1z
17a9e65961SEric Fiselier
18a9e65961SEric Fiseliernamespace std {
19e3bdfe63SCasey Carter  // 23.6.3, optional for object types
20a9e65961SEric Fiselier  template <class T> class optional;
21a9e65961SEric Fiselier
22e3bdfe63SCasey Carter  // 23.6.4, no-value state indicator
23a9e65961SEric Fiselier  struct nullopt_t{see below };
2440a01d53SMarshall Clow  inline constexpr nullopt_t nullopt(unspecified );
25a9e65961SEric Fiselier
26e3bdfe63SCasey Carter  // 23.6.5, class bad_optional_access
27a9e65961SEric Fiselier  class bad_optional_access;
28a9e65961SEric Fiselier
29e3bdfe63SCasey Carter  // 23.6.6, relational operators
30e3bdfe63SCasey Carter  template <class T, class U>
31e3bdfe63SCasey Carter  constexpr bool operator==(const optional<T>&, const optional<U>&);
32e3bdfe63SCasey Carter  template <class T, class U>
33e3bdfe63SCasey Carter  constexpr bool operator!=(const optional<T>&, const optional<U>&);
34e3bdfe63SCasey Carter  template <class T, class U>
35e3bdfe63SCasey Carter  constexpr bool operator<(const optional<T>&, const optional<U>&);
36e3bdfe63SCasey Carter  template <class T, class U>
37e3bdfe63SCasey Carter  constexpr bool operator>(const optional<T>&, const optional<U>&);
38e3bdfe63SCasey Carter  template <class T, class U>
39e3bdfe63SCasey Carter  constexpr bool operator<=(const optional<T>&, const optional<U>&);
40e3bdfe63SCasey Carter  template <class T, class U>
41e3bdfe63SCasey Carter  constexpr bool operator>=(const optional<T>&, const optional<U>&);
42e3bdfe63SCasey Carter
43e3bdfe63SCasey Carter  // 23.6.7 comparison with nullopt
44a9e65961SEric Fiselier  template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
45a9e65961SEric Fiselier  template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
46a9e65961SEric Fiselier  template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
47a9e65961SEric Fiselier  template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
48a9e65961SEric Fiselier  template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
49a9e65961SEric Fiselier  template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
50a9e65961SEric Fiselier  template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
51a9e65961SEric Fiselier  template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
52a9e65961SEric Fiselier  template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
53a9e65961SEric Fiselier  template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
54a9e65961SEric Fiselier  template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
55a9e65961SEric Fiselier  template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
56a9e65961SEric Fiselier
57e3bdfe63SCasey Carter  // 23.6.8, comparison with T
58e3bdfe63SCasey Carter  template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
5913e6e61bSMarshall Clow  template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
60e3bdfe63SCasey Carter  template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
6113e6e61bSMarshall Clow  template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
62e3bdfe63SCasey Carter  template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
6313e6e61bSMarshall Clow  template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
64e3bdfe63SCasey Carter  template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
6513e6e61bSMarshall Clow  template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
66e3bdfe63SCasey Carter  template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
6713e6e61bSMarshall Clow  template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
68e3bdfe63SCasey Carter  template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
6913e6e61bSMarshall Clow  template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
70a9e65961SEric Fiselier
71e3bdfe63SCasey Carter  // 23.6.9, specialized algorithms
7254644993SChristopher Di Bella  template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
73a9e65961SEric Fiselier  template <class T> constexpr optional<see below > make_optional(T&&);
74a9e65961SEric Fiselier  template <class T, class... Args>
75a9e65961SEric Fiselier    constexpr optional<T> make_optional(Args&&... args);
76a9e65961SEric Fiselier  template <class T, class U, class... Args>
77a9e65961SEric Fiselier    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
78a9e65961SEric Fiselier
79e3bdfe63SCasey Carter  // 23.6.10, hash support
80a9e65961SEric Fiselier  template <class T> struct hash;
81a9e65961SEric Fiselier  template <class T> struct hash<optional<T>>;
82a9e65961SEric Fiselier
83a9e65961SEric Fiselier  template <class T> class optional {
84a9e65961SEric Fiselier  public:
85a9e65961SEric Fiselier    using value_type = T;
86a9e65961SEric Fiselier
87e3bdfe63SCasey Carter    // 23.6.3.1, constructors
88a9e65961SEric Fiselier    constexpr optional() noexcept;
89a9e65961SEric Fiselier    constexpr optional(nullopt_t) noexcept;
90a9e65961SEric Fiselier    optional(const optional &);
91a9e65961SEric Fiselier    optional(optional &&) noexcept(see below);
92a9e65961SEric Fiselier    template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
93a9e65961SEric Fiselier    template <class U, class... Args>
94a9e65961SEric Fiselier      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
95a9e65961SEric Fiselier    template <class U = T>
969e5c2934SMark de Wever      constexpr explicit(see-below) optional(U &&);
97a9e65961SEric Fiselier    template <class U>
989e5c2934SMark de Wever      explicit(see-below) optional(const optional<U> &);         // constexpr in C++20
99a9e65961SEric Fiselier    template <class U>
1009e5c2934SMark de Wever      explicit(see-below) optional(optional<U> &&);              // constexpr in C++20
101a9e65961SEric Fiselier
102e3bdfe63SCasey Carter    // 23.6.3.2, destructor
10354644993SChristopher Di Bella    ~optional(); // constexpr in C++20
104a9e65961SEric Fiselier
105e3bdfe63SCasey Carter    // 23.6.3.3, assignment
10654644993SChristopher Di Bella    optional &operator=(nullopt_t) noexcept;                     // constexpr in C++20
1071d5f6a81SLouis Dionne    optional &operator=(const optional &);                       // constexpr in C++20
1081d5f6a81SLouis Dionne    optional &operator=(optional &&) noexcept(see below);        // constexpr in C++20
10954644993SChristopher Di Bella    template <class U = T> optional &operator=(U &&);            // constexpr in C++20
11054644993SChristopher Di Bella    template <class U> optional &operator=(const optional<U> &); // constexpr in C++20
11154644993SChristopher Di Bella    template <class U> optional &operator=(optional<U> &&);      // constexpr in C++20
11254644993SChristopher Di Bella    template <class... Args> T& emplace(Args &&...);             // constexpr in C++20
113a9e65961SEric Fiselier    template <class U, class... Args>
11454644993SChristopher Di Bella      T& emplace(initializer_list<U>, Args &&...);               // constexpr in C++20
115a9e65961SEric Fiselier
116e3bdfe63SCasey Carter    // 23.6.3.4, swap
11754644993SChristopher Di Bella    void swap(optional &) noexcept(see below ); // constexpr in C++20
118a9e65961SEric Fiselier
119e3bdfe63SCasey Carter    // 23.6.3.5, observers
120a9e65961SEric Fiselier    constexpr T const *operator->() const;
121a9e65961SEric Fiselier    constexpr T *operator->();
122a9e65961SEric Fiselier    constexpr T const &operator*() const &;
123a9e65961SEric Fiselier    constexpr T &operator*() &;
124a9e65961SEric Fiselier    constexpr T &&operator*() &&;
125a9e65961SEric Fiselier    constexpr const T &&operator*() const &&;
126a9e65961SEric Fiselier    constexpr explicit operator bool() const noexcept;
127a9e65961SEric Fiselier    constexpr bool has_value() const noexcept;
128a9e65961SEric Fiselier    constexpr T const &value() const &;
129a9e65961SEric Fiselier    constexpr T &value() &;
130a9e65961SEric Fiselier    constexpr T &&value() &&;
131a9e65961SEric Fiselier    constexpr const T &&value() const &&;
132a9e65961SEric Fiselier    template <class U> constexpr T value_or(U &&) const &;
133a9e65961SEric Fiselier    template <class U> constexpr T value_or(U &&) &&;
134a9e65961SEric Fiselier
13517cfc57dSNikolas Klauser    // [optional.monadic], monadic operations
13617cfc57dSNikolas Klauser    template<class F> constexpr auto and_then(F&& f) &;         // since C++23
13717cfc57dSNikolas Klauser    template<class F> constexpr auto and_then(F&& f) &&;        // since C++23
13817cfc57dSNikolas Klauser    template<class F> constexpr auto and_then(F&& f) const&;    // since C++23
13917cfc57dSNikolas Klauser    template<class F> constexpr auto and_then(F&& f) const&&;   // since C++23
14017cfc57dSNikolas Klauser    template<class F> constexpr auto transform(F&& f) &;        // since C++23
14117cfc57dSNikolas Klauser    template<class F> constexpr auto transform(F&& f) &&;       // since C++23
14217cfc57dSNikolas Klauser    template<class F> constexpr auto transform(F&& f) const&;   // since C++23
14317cfc57dSNikolas Klauser    template<class F> constexpr auto transform(F&& f) const&&;  // since C++23
14417cfc57dSNikolas Klauser    template<class F> constexpr optional or_else(F&& f) &&;     // since C++23
14517cfc57dSNikolas Klauser    template<class F> constexpr optional or_else(F&& f) const&; // since C++23
14617cfc57dSNikolas Klauser
147e3bdfe63SCasey Carter    // 23.6.3.6, modifiers
14854644993SChristopher Di Bella    void reset() noexcept; // constexpr in C++20
149a9e65961SEric Fiselier
150a9e65961SEric Fiselier  private:
151a9e65961SEric Fiselier    T *val; // exposition only
152a9e65961SEric Fiselier  };
153f35b4bc3SMarshall Clow
154f35b4bc3SMarshall Clowtemplate<class T>
155f35b4bc3SMarshall Clow  optional(T) -> optional<T>;
156f35b4bc3SMarshall Clow
157a9e65961SEric Fiselier} // namespace std
158a9e65961SEric Fiselier
159a9e65961SEric Fiselier*/
160a9e65961SEric Fiselier
161385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
1622eadbc86SLouis Dionne#include <__availability>
16317cfc57dSNikolas Klauser#include <__concepts/invocable.h>
164bfbd73f8SArthur O'Dwyer#include <__config>
165faef447eSNikolas Klauser#include <__functional/hash.h>
166faef447eSNikolas Klauser#include <__functional/invoke.h>
167faef447eSNikolas Klauser#include <__functional/unary_function.h>
168faef447eSNikolas Klauser#include <__memory/construct_at.h>
169faef447eSNikolas Klauser#include <__tuple>
170faef447eSNikolas Klauser#include <__utility/forward.h>
17152915d78SNikolas Klauser#include <__utility/in_place.h>
172faef447eSNikolas Klauser#include <__utility/move.h>
17352915d78SNikolas Klauser#include <__utility/swap.h>
174a9e65961SEric Fiselier#include <initializer_list>
175a9e65961SEric Fiselier#include <new>
176a9e65961SEric Fiselier#include <stdexcept>
177a9e65961SEric Fiselier#include <type_traits>
178f56972e2SMarshall Clow#include <version>
179a9e65961SEric Fiselier
180*de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
181*de4a57cbSLouis Dionne#  include <atomic>
182*de4a57cbSLouis Dionne#  include <chrono>
183*de4a57cbSLouis Dionne#  include <climits>
184*de4a57cbSLouis Dionne#  include <concepts>
185*de4a57cbSLouis Dionne#  include <ctime>
186*de4a57cbSLouis Dionne#  include <iterator>
187*de4a57cbSLouis Dionne#  include <memory>
188*de4a57cbSLouis Dionne#  include <ratio>
189*de4a57cbSLouis Dionne#  include <tuple>
190*de4a57cbSLouis Dionne#  include <typeinfo>
191*de4a57cbSLouis Dionne#  include <utility>
192*de4a57cbSLouis Dionne#  include <variant>
193*de4a57cbSLouis Dionne#endif
194*de4a57cbSLouis Dionne
195db1978b6SNikolas Klauser// standard-mandated includes
196db1978b6SNikolas Klauser#include <compare>
197db1978b6SNikolas Klauser
198a9e65961SEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
199a9e65961SEric Fiselier#  pragma GCC system_header
200a9e65961SEric Fiselier#endif
201a9e65961SEric Fiselier
202a9e65961SEric Fiseliernamespace std  // purposefully not using versioning namespace
203a9e65961SEric Fiselier{
204a9e65961SEric Fiselier
2058a063df1SLouis Dionneclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
206e29b1ed5SMarshall Clow    : public exception
207a9e65961SEric Fiselier{
208a9e65961SEric Fiselierpublic:
209a9e65961SEric Fiselier    // Get the key function ~bad_optional_access() into the dylib
2106a1d0785SMarshall Clow    virtual ~bad_optional_access() _NOEXCEPT;
211e29b1ed5SMarshall Clow    virtual const char* what() const _NOEXCEPT;
212a9e65961SEric Fiselier};
213a9e65961SEric Fiselier
214d2b0df35SNikolas Klauser} // namespace std
215a9e65961SEric Fiselier
216a9e65961SEric Fiselier#if _LIBCPP_STD_VER > 14
217a9e65961SEric Fiselier
218a9e65961SEric Fiselier_LIBCPP_BEGIN_NAMESPACE_STD
219a9e65961SEric Fiselier
220a9e65961SEric Fiselier_LIBCPP_NORETURN
221a9e65961SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
2228a063df1SLouis Dionne_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
223a9e65961SEric Fiseliervoid __throw_bad_optional_access() {
224a9e65961SEric Fiselier#ifndef _LIBCPP_NO_EXCEPTIONS
225a9e65961SEric Fiselier        throw bad_optional_access();
226a9e65961SEric Fiselier#else
227a9e65961SEric Fiselier        _VSTD::abort();
228a9e65961SEric Fiselier#endif
229a9e65961SEric Fiselier}
230a9e65961SEric Fiselier
231a9e65961SEric Fiselierstruct nullopt_t
232a9e65961SEric Fiselier{
233a9e65961SEric Fiselier    struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
234a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
235a9e65961SEric Fiselier};
236a9e65961SEric Fiselier
237cb793e1aSLouis Dionneinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
238a9e65961SEric Fiselier
23917cfc57dSNikolas Klauserstruct __optional_construct_from_invoke_tag {};
24017cfc57dSNikolas Klauser
241a9e65961SEric Fiseliertemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
242a9e65961SEric Fiselierstruct __optional_destruct_base;
243a9e65961SEric Fiselier
244a9e65961SEric Fiseliertemplate <class _Tp>
245a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, false>
246a9e65961SEric Fiselier{
247a9e65961SEric Fiselier    typedef _Tp value_type;
248a9e65961SEric Fiselier    static_assert(is_object_v<value_type>,
249a9e65961SEric Fiselier        "instantiation of optional with a non-object type is undefined behavior");
250a9e65961SEric Fiselier    union
251a9e65961SEric Fiselier    {
252a9e65961SEric Fiselier        char __null_state_;
253a9e65961SEric Fiselier        value_type __val_;
254a9e65961SEric Fiselier    };
255a9e65961SEric Fiselier    bool __engaged_;
256a9e65961SEric Fiselier
257a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
25854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
259a9e65961SEric Fiselier    {
260a9e65961SEric Fiselier        if (__engaged_)
261a9e65961SEric Fiselier            __val_.~value_type();
262a9e65961SEric Fiselier    }
263a9e65961SEric Fiselier
264a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
265a9e65961SEric Fiselier    constexpr __optional_destruct_base() noexcept
266a9e65961SEric Fiselier        :  __null_state_(),
267a9e65961SEric Fiselier           __engaged_(false) {}
268a9e65961SEric Fiselier
269a9e65961SEric Fiselier    template <class... _Args>
270a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
271a9e65961SEric Fiselier    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
272a9e65961SEric Fiselier        :  __val_(_VSTD::forward<_Args>(__args)...),
273a9e65961SEric Fiselier           __engaged_(true) {}
274a9e65961SEric Fiselier
27517cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
27617cfc57dSNikolas Klauser  template <class _Fp, class... _Args>
27717cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
27817cfc57dSNikolas Klauser  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
27917cfc57dSNikolas Klauser      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
28017cfc57dSNikolas Klauser#endif
28117cfc57dSNikolas Klauser
282a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
28354644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
284a9e65961SEric Fiselier    {
285a9e65961SEric Fiselier        if (__engaged_)
286a9e65961SEric Fiselier        {
287a9e65961SEric Fiselier            __val_.~value_type();
288a9e65961SEric Fiselier            __engaged_ = false;
289a9e65961SEric Fiselier        }
290a9e65961SEric Fiselier    }
291a9e65961SEric Fiselier};
292a9e65961SEric Fiselier
293a9e65961SEric Fiseliertemplate <class _Tp>
294a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, true>
295a9e65961SEric Fiselier{
296a9e65961SEric Fiselier    typedef _Tp value_type;
297a9e65961SEric Fiselier    static_assert(is_object_v<value_type>,
298a9e65961SEric Fiselier        "instantiation of optional with a non-object type is undefined behavior");
299a9e65961SEric Fiselier    union
300a9e65961SEric Fiselier    {
301a9e65961SEric Fiselier        char __null_state_;
302a9e65961SEric Fiselier        value_type __val_;
303a9e65961SEric Fiselier    };
304a9e65961SEric Fiselier    bool __engaged_;
305a9e65961SEric Fiselier
306a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
307a9e65961SEric Fiselier    constexpr __optional_destruct_base() noexcept
308a9e65961SEric Fiselier        :  __null_state_(),
309a9e65961SEric Fiselier           __engaged_(false) {}
310a9e65961SEric Fiselier
311a9e65961SEric Fiselier    template <class... _Args>
312a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
313a9e65961SEric Fiselier    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
314a9e65961SEric Fiselier        :  __val_(_VSTD::forward<_Args>(__args)...),
315a9e65961SEric Fiselier           __engaged_(true) {}
316a9e65961SEric Fiselier
31717cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
31817cfc57dSNikolas Klauser  template <class _Fp, class... _Args>
31917cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
32017cfc57dSNikolas Klauser  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
32117cfc57dSNikolas Klauser      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
32217cfc57dSNikolas Klauser#endif
32317cfc57dSNikolas Klauser
324a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
32554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
326a9e65961SEric Fiselier    {
327a9e65961SEric Fiselier        if (__engaged_)
328a9e65961SEric Fiselier        {
329a9e65961SEric Fiselier            __engaged_ = false;
330a9e65961SEric Fiselier        }
331a9e65961SEric Fiselier    }
332a9e65961SEric Fiselier};
333a9e65961SEric Fiselier
334a9e65961SEric Fiseliertemplate <class _Tp, bool = is_reference<_Tp>::value>
335a9e65961SEric Fiselierstruct __optional_storage_base : __optional_destruct_base<_Tp>
336a9e65961SEric Fiselier{
337a9e65961SEric Fiselier    using __base = __optional_destruct_base<_Tp>;
338a9e65961SEric Fiselier    using value_type = _Tp;
339a9e65961SEric Fiselier    using __base::__base;
340a9e65961SEric Fiselier
341a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
342a9e65961SEric Fiselier    constexpr bool has_value() const noexcept
343a9e65961SEric Fiselier    {
344a9e65961SEric Fiselier        return this->__engaged_;
345a9e65961SEric Fiselier    }
346a9e65961SEric Fiselier
347a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
348a9e65961SEric Fiselier    constexpr value_type& __get() & noexcept
349a9e65961SEric Fiselier    {
350a9e65961SEric Fiselier        return this->__val_;
351a9e65961SEric Fiselier    }
352a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
353a9e65961SEric Fiselier    constexpr const value_type& __get() const& noexcept
354a9e65961SEric Fiselier    {
355a9e65961SEric Fiselier        return this->__val_;
356a9e65961SEric Fiselier    }
357a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
358a9e65961SEric Fiselier    constexpr value_type&& __get() && noexcept
359a9e65961SEric Fiselier    {
360a9e65961SEric Fiselier        return _VSTD::move(this->__val_);
361a9e65961SEric Fiselier    }
362a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
363a9e65961SEric Fiselier    constexpr const value_type&& __get() const&& noexcept
364a9e65961SEric Fiselier    {
365a9e65961SEric Fiselier        return _VSTD::move(this->__val_);
366a9e65961SEric Fiselier    }
367a9e65961SEric Fiselier
368a9e65961SEric Fiselier    template <class... _Args>
369a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
37054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
371a9e65961SEric Fiselier    {
372a9e65961SEric Fiselier        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
37354644993SChristopher Di Bella#if _LIBCPP_STD_VER > 17
37454644993SChristopher Di Bella        _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
37554644993SChristopher Di Bella#else
376a9e65961SEric Fiselier        ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
37754644993SChristopher Di Bella#endif
378a9e65961SEric Fiselier        this->__engaged_ = true;
379a9e65961SEric Fiselier    }
380a9e65961SEric Fiselier
381a9e65961SEric Fiselier    template <class _That>
382a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
38354644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
384a9e65961SEric Fiselier    {
385a9e65961SEric Fiselier        if (__opt.has_value())
386a9e65961SEric Fiselier            __construct(_VSTD::forward<_That>(__opt).__get());
387a9e65961SEric Fiselier    }
388a9e65961SEric Fiselier
389a9e65961SEric Fiselier    template <class _That>
390a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
39154644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
392a9e65961SEric Fiselier    {
393a9e65961SEric Fiselier        if (this->__engaged_ == __opt.has_value())
394a9e65961SEric Fiselier        {
395a9e65961SEric Fiselier            if (this->__engaged_)
396a9e65961SEric Fiselier                this->__val_ = _VSTD::forward<_That>(__opt).__get();
397a9e65961SEric Fiselier        }
398a9e65961SEric Fiselier        else
399a9e65961SEric Fiselier        {
400a9e65961SEric Fiselier            if (this->__engaged_)
401a9e65961SEric Fiselier                this->reset();
402a9e65961SEric Fiselier            else
403a9e65961SEric Fiselier                __construct(_VSTD::forward<_That>(__opt).__get());
404a9e65961SEric Fiselier        }
405a9e65961SEric Fiselier    }
406a9e65961SEric Fiselier};
407a9e65961SEric Fiselier
4087b291b6fSWill Hawkins// optional<T&> is currently required to be ill-formed. However, it may
4097b291b6fSWill Hawkins// be allowed in the future. For this reason, it has already been implemented
4107b291b6fSWill Hawkins// to ensure we can make the change in an ABI-compatible manner.
411a9e65961SEric Fiseliertemplate <class _Tp>
412a9e65961SEric Fiselierstruct __optional_storage_base<_Tp, true>
413a9e65961SEric Fiselier{
414a9e65961SEric Fiselier    using value_type = _Tp;
415a9e65961SEric Fiselier    using __raw_type = remove_reference_t<_Tp>;
416a9e65961SEric Fiselier    __raw_type* __value_;
417a9e65961SEric Fiselier
418a9e65961SEric Fiselier    template <class _Up>
419a9e65961SEric Fiselier    static constexpr bool __can_bind_reference() {
420a9e65961SEric Fiselier        using _RawUp = typename remove_reference<_Up>::type;
421a9e65961SEric Fiselier        using _UpPtr = _RawUp*;
422a9e65961SEric Fiselier        using _RawTp = typename remove_reference<_Tp>::type;
423a9e65961SEric Fiselier        using _TpPtr = _RawTp*;
424a9e65961SEric Fiselier        using _CheckLValueArg = integral_constant<bool,
425a9e65961SEric Fiselier            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
426a9e65961SEric Fiselier        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
427a9e65961SEric Fiselier        ||  is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
428a9e65961SEric Fiselier        >;
429a9e65961SEric Fiselier        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
430a9e65961SEric Fiselier            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
431a9e65961SEric Fiselier                is_convertible<_UpPtr, _TpPtr>::value);
432a9e65961SEric Fiselier    }
433a9e65961SEric Fiselier
434a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
435a9e65961SEric Fiselier    constexpr __optional_storage_base() noexcept
436a9e65961SEric Fiselier        :  __value_(nullptr) {}
437a9e65961SEric Fiselier
438a9e65961SEric Fiselier    template <class _UArg>
439a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
440a9e65961SEric Fiselier    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
441a9e65961SEric Fiselier        :  __value_(_VSTD::addressof(__uarg))
442a9e65961SEric Fiselier    {
443a9e65961SEric Fiselier      static_assert(__can_bind_reference<_UArg>(),
444a9e65961SEric Fiselier        "Attempted to construct a reference element in tuple from a "
445a9e65961SEric Fiselier        "possible temporary");
446a9e65961SEric Fiselier    }
447a9e65961SEric Fiselier
448a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
44954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
450a9e65961SEric Fiselier
451a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
452a9e65961SEric Fiselier    constexpr bool has_value() const noexcept
453a9e65961SEric Fiselier      { return __value_ != nullptr; }
454a9e65961SEric Fiselier
455a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
456a9e65961SEric Fiselier    constexpr value_type& __get() const& noexcept
457a9e65961SEric Fiselier      { return *__value_; }
458a9e65961SEric Fiselier
459a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
460a9e65961SEric Fiselier    constexpr value_type&& __get() const&& noexcept
461a9e65961SEric Fiselier      { return _VSTD::forward<value_type>(*__value_); }
462a9e65961SEric Fiselier
463a9e65961SEric Fiselier    template <class _UArg>
464a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
46554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
466a9e65961SEric Fiselier    {
467a9e65961SEric Fiselier        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
468a9e65961SEric Fiselier        static_assert(__can_bind_reference<_UArg>(),
469a9e65961SEric Fiselier            "Attempted to construct a reference element in tuple from a "
470a9e65961SEric Fiselier            "possible temporary");
471a9e65961SEric Fiselier        __value_ = _VSTD::addressof(__val);
472a9e65961SEric Fiselier    }
473a9e65961SEric Fiselier
474a9e65961SEric Fiselier    template <class _That>
475a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
47654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
477a9e65961SEric Fiselier    {
478a9e65961SEric Fiselier        if (__opt.has_value())
479a9e65961SEric Fiselier            __construct(_VSTD::forward<_That>(__opt).__get());
480a9e65961SEric Fiselier    }
481a9e65961SEric Fiselier
482a9e65961SEric Fiselier    template <class _That>
483a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
48454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
485a9e65961SEric Fiselier    {
486a9e65961SEric Fiselier        if (has_value() == __opt.has_value())
487a9e65961SEric Fiselier        {
488a9e65961SEric Fiselier            if (has_value())
489a9e65961SEric Fiselier                *__value_ = _VSTD::forward<_That>(__opt).__get();
490a9e65961SEric Fiselier        }
491a9e65961SEric Fiselier        else
492a9e65961SEric Fiselier        {
493a9e65961SEric Fiselier            if (has_value())
494a9e65961SEric Fiselier                reset();
495a9e65961SEric Fiselier            else
496a9e65961SEric Fiselier                __construct(_VSTD::forward<_That>(__opt).__get());
497a9e65961SEric Fiselier        }
498a9e65961SEric Fiselier    }
499a9e65961SEric Fiselier};
500a9e65961SEric Fiselier
501f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
502f2d571c8SCasey Carterstruct __optional_copy_base : __optional_storage_base<_Tp>
503a9e65961SEric Fiselier{
504a9e65961SEric Fiselier    using __optional_storage_base<_Tp>::__optional_storage_base;
505a9e65961SEric Fiselier};
506a9e65961SEric Fiselier
507a9e65961SEric Fiseliertemplate <class _Tp>
508f2d571c8SCasey Carterstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
509a9e65961SEric Fiselier{
510a9e65961SEric Fiselier    using __optional_storage_base<_Tp>::__optional_storage_base;
511a9e65961SEric Fiselier
512a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
513f2d571c8SCasey Carter    __optional_copy_base() = default;
514a9e65961SEric Fiselier
515a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
51654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
517a9e65961SEric Fiselier    {
518a9e65961SEric Fiselier        this->__construct_from(__opt);
519a9e65961SEric Fiselier    }
520a9e65961SEric Fiselier
521a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
522f2d571c8SCasey Carter    __optional_copy_base(__optional_copy_base&&) = default;
523f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
524f2d571c8SCasey Carter    __optional_copy_base& operator=(const __optional_copy_base&) = default;
525f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
526f2d571c8SCasey Carter    __optional_copy_base& operator=(__optional_copy_base&&) = default;
527f2d571c8SCasey Carter};
528f2d571c8SCasey Carter
529f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
530f2d571c8SCasey Carterstruct __optional_move_base : __optional_copy_base<_Tp>
531f2d571c8SCasey Carter{
532f2d571c8SCasey Carter    using __optional_copy_base<_Tp>::__optional_copy_base;
533f2d571c8SCasey Carter};
534f2d571c8SCasey Carter
535f2d571c8SCasey Cartertemplate <class _Tp>
536f2d571c8SCasey Carterstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
537f2d571c8SCasey Carter{
538f2d571c8SCasey Carter    using value_type = _Tp;
539f2d571c8SCasey Carter    using __optional_copy_base<_Tp>::__optional_copy_base;
540f2d571c8SCasey Carter
541f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
542f2d571c8SCasey Carter    __optional_move_base() = default;
543f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
544f2d571c8SCasey Carter    __optional_move_base(const __optional_move_base&) = default;
545f2d571c8SCasey Carter
546f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
54754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
548a9e65961SEric Fiselier        noexcept(is_nothrow_move_constructible_v<value_type>)
549a9e65961SEric Fiselier    {
550a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__opt));
551a9e65961SEric Fiselier    }
552a9e65961SEric Fiselier
553a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
554f2d571c8SCasey Carter    __optional_move_base& operator=(const __optional_move_base&) = default;
555f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
556f2d571c8SCasey Carter    __optional_move_base& operator=(__optional_move_base&&) = default;
557f2d571c8SCasey Carter};
558f2d571c8SCasey Carter
559f2d571c8SCasey Cartertemplate <class _Tp, bool =
560f2d571c8SCasey Carter    is_trivially_destructible<_Tp>::value &&
561f2d571c8SCasey Carter    is_trivially_copy_constructible<_Tp>::value &&
562f2d571c8SCasey Carter    is_trivially_copy_assignable<_Tp>::value>
563f2d571c8SCasey Carterstruct __optional_copy_assign_base : __optional_move_base<_Tp>
564f2d571c8SCasey Carter{
565f2d571c8SCasey Carter    using __optional_move_base<_Tp>::__optional_move_base;
566f2d571c8SCasey Carter};
567f2d571c8SCasey Carter
568f2d571c8SCasey Cartertemplate <class _Tp>
569f2d571c8SCasey Carterstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
570f2d571c8SCasey Carter{
571f2d571c8SCasey Carter    using __optional_move_base<_Tp>::__optional_move_base;
572f2d571c8SCasey Carter
573f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
574f2d571c8SCasey Carter    __optional_copy_assign_base() = default;
575f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
576f2d571c8SCasey Carter    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
577f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
578f2d571c8SCasey Carter    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
579f2d571c8SCasey Carter
580f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
58154644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
582a9e65961SEric Fiselier    {
583a9e65961SEric Fiselier        this->__assign_from(__opt);
584a9e65961SEric Fiselier        return *this;
585a9e65961SEric Fiselier    }
586a9e65961SEric Fiselier
587a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
588f2d571c8SCasey Carter    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
589f2d571c8SCasey Carter};
590f2d571c8SCasey Carter
591f2d571c8SCasey Cartertemplate <class _Tp, bool =
592f2d571c8SCasey Carter    is_trivially_destructible<_Tp>::value &&
593f2d571c8SCasey Carter    is_trivially_move_constructible<_Tp>::value &&
594f2d571c8SCasey Carter    is_trivially_move_assignable<_Tp>::value>
595f2d571c8SCasey Carterstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
596f2d571c8SCasey Carter{
597f2d571c8SCasey Carter    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
598f2d571c8SCasey Carter};
599f2d571c8SCasey Carter
600f2d571c8SCasey Cartertemplate <class _Tp>
601f2d571c8SCasey Carterstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
602f2d571c8SCasey Carter{
603f2d571c8SCasey Carter    using value_type = _Tp;
604f2d571c8SCasey Carter    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
605f2d571c8SCasey Carter
606f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
607f2d571c8SCasey Carter    __optional_move_assign_base() = default;
608f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
609f2d571c8SCasey Carter    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
610f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
611f2d571c8SCasey Carter    __optional_move_assign_base(__optional_move_assign_base&&) = default;
612f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
613f2d571c8SCasey Carter    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
614f2d571c8SCasey Carter
615f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
61654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
617a9e65961SEric Fiselier        noexcept(is_nothrow_move_assignable_v<value_type> &&
618a9e65961SEric Fiselier                 is_nothrow_move_constructible_v<value_type>)
619a9e65961SEric Fiselier    {
620a9e65961SEric Fiselier        this->__assign_from(_VSTD::move(__opt));
621a9e65961SEric Fiselier        return *this;
622a9e65961SEric Fiselier    }
623a9e65961SEric Fiselier};
624a9e65961SEric Fiselier
625a9e65961SEric Fiseliertemplate <class _Tp>
626a9e65961SEric Fiselierusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
627a9e65961SEric Fiselier    is_copy_constructible<_Tp>::value,
628a9e65961SEric Fiselier    is_move_constructible<_Tp>::value
629a9e65961SEric Fiselier>;
630a9e65961SEric Fiselier
631a9e65961SEric Fiseliertemplate <class _Tp>
632a9e65961SEric Fiselierusing __optional_sfinae_assign_base_t = __sfinae_assign_base<
633a9e65961SEric Fiselier    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
634a9e65961SEric Fiselier    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
635a9e65961SEric Fiselier>;
636a9e65961SEric Fiselier
637a9e65961SEric Fiseliertemplate<class _Tp>
63817cfc57dSNikolas Klauserclass optional;
63917cfc57dSNikolas Klausertemplate <class _Tp>
64017cfc57dSNikolas Klauserstruct __is_std_optional : false_type {};
64117cfc57dSNikolas Klausertemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
64217cfc57dSNikolas Klauser
64317cfc57dSNikolas Klausertemplate <class _Tp>
644a9e65961SEric Fiselierclass optional
645f2d571c8SCasey Carter    : private __optional_move_assign_base<_Tp>
646a9e65961SEric Fiselier    , private __optional_sfinae_ctor_base_t<_Tp>
647a9e65961SEric Fiselier    , private __optional_sfinae_assign_base_t<_Tp>
648a9e65961SEric Fiselier{
649f2d571c8SCasey Carter    using __base = __optional_move_assign_base<_Tp>;
650a9e65961SEric Fiselierpublic:
651a9e65961SEric Fiselier    using value_type = _Tp;
652a9e65961SEric Fiselier
653a9e65961SEric Fiselierprivate:
654a9e65961SEric Fiselier     // Disable the reference extension using this static assert.
65536db4898SMarshall Clow    static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
656a9e65961SEric Fiselier        "instantiation of optional with in_place_t is ill-formed");
657a9e65961SEric Fiselier    static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
658a9e65961SEric Fiselier        "instantiation of optional with nullopt_t is ill-formed");
659a9e65961SEric Fiselier    static_assert(!is_reference_v<value_type>,
660a9e65961SEric Fiselier        "instantiation of optional with a reference type is ill-formed");
661a9e65961SEric Fiselier    static_assert(is_destructible_v<value_type>,
662a9e65961SEric Fiselier        "instantiation of optional with a non-destructible type is ill-formed");
66336db4898SMarshall Clow    static_assert(!is_array_v<value_type>,
66436db4898SMarshall Clow        "instantiation of optional with an array type is ill-formed");
665a9e65961SEric Fiselier
666a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from _Up
667a9e65961SEric Fiselier    struct _CheckOptionalArgsConstructor {
668a9e65961SEric Fiselier      template <class _Up>
669a9e65961SEric Fiselier      static constexpr bool __enable_implicit() {
670a9e65961SEric Fiselier          return is_constructible_v<_Tp, _Up&&> &&
671a9e65961SEric Fiselier                 is_convertible_v<_Up&&, _Tp>;
672a9e65961SEric Fiselier      }
673a9e65961SEric Fiselier
674a9e65961SEric Fiselier      template <class _Up>
675a9e65961SEric Fiselier      static constexpr bool __enable_explicit() {
676a9e65961SEric Fiselier          return is_constructible_v<_Tp, _Up&&> &&
677a9e65961SEric Fiselier                 !is_convertible_v<_Up&&, _Tp>;
678a9e65961SEric Fiselier      }
679a9e65961SEric Fiselier    };
680a9e65961SEric Fiselier    template <class _Up>
6813359a17bSEric Fiselier    using _CheckOptionalArgsCtor = _If<
6823359a17bSEric Fiselier        _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
6833359a17bSEric Fiselier        _IsNotSame<__uncvref_t<_Up>, optional>::value,
684a9e65961SEric Fiselier        _CheckOptionalArgsConstructor,
685a9e65961SEric Fiselier        __check_tuple_constructor_fail
686a9e65961SEric Fiselier    >;
687a9e65961SEric Fiselier    template <class _QualUp>
688a9e65961SEric Fiselier    struct _CheckOptionalLikeConstructor {
689a9e65961SEric Fiselier      template <class _Up, class _Opt = optional<_Up>>
6903359a17bSEric Fiselier      using __check_constructible_from_opt = _Or<
691a9e65961SEric Fiselier          is_constructible<_Tp, _Opt&>,
692a9e65961SEric Fiselier          is_constructible<_Tp, _Opt const&>,
693a9e65961SEric Fiselier          is_constructible<_Tp, _Opt&&>,
694a9e65961SEric Fiselier          is_constructible<_Tp, _Opt const&&>,
695a9e65961SEric Fiselier          is_convertible<_Opt&, _Tp>,
696a9e65961SEric Fiselier          is_convertible<_Opt const&, _Tp>,
697a9e65961SEric Fiselier          is_convertible<_Opt&&, _Tp>,
698a9e65961SEric Fiselier          is_convertible<_Opt const&&, _Tp>
699a9e65961SEric Fiselier      >;
700a9e65961SEric Fiselier      template <class _Up, class _Opt = optional<_Up>>
7013359a17bSEric Fiselier      using __check_assignable_from_opt = _Or<
702a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt&>,
703a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt const&>,
704a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt&&>,
705a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt const&&>
706a9e65961SEric Fiselier      >;
707a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
708a9e65961SEric Fiselier      static constexpr bool __enable_implicit() {
709a9e65961SEric Fiselier          return is_convertible<_QUp, _Tp>::value &&
710a9e65961SEric Fiselier              !__check_constructible_from_opt<_Up>::value;
711a9e65961SEric Fiselier      }
712a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
713a9e65961SEric Fiselier      static constexpr bool __enable_explicit() {
714a9e65961SEric Fiselier          return !is_convertible<_QUp, _Tp>::value &&
715a9e65961SEric Fiselier              !__check_constructible_from_opt<_Up>::value;
716a9e65961SEric Fiselier      }
717a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
718a9e65961SEric Fiselier      static constexpr bool __enable_assign() {
719b6f19174SArthur O'Dwyer          // Construction and assignability of _QUp to _Tp has already been
720a9e65961SEric Fiselier          // checked.
721a9e65961SEric Fiselier          return !__check_constructible_from_opt<_Up>::value &&
722a9e65961SEric Fiselier              !__check_assignable_from_opt<_Up>::value;
723a9e65961SEric Fiselier      }
724a9e65961SEric Fiselier    };
725a9e65961SEric Fiselier
726a9e65961SEric Fiselier    template <class _Up, class _QualUp>
7273359a17bSEric Fiselier    using _CheckOptionalLikeCtor = _If<
7283359a17bSEric Fiselier      _And<
7293359a17bSEric Fiselier         _IsNotSame<_Up, _Tp>,
730a9e65961SEric Fiselier          is_constructible<_Tp, _QualUp>
731a9e65961SEric Fiselier      >::value,
732a9e65961SEric Fiselier      _CheckOptionalLikeConstructor<_QualUp>,
733a9e65961SEric Fiselier      __check_tuple_constructor_fail
734a9e65961SEric Fiselier    >;
735a9e65961SEric Fiselier    template <class _Up, class _QualUp>
7363359a17bSEric Fiselier    using _CheckOptionalLikeAssign = _If<
7373359a17bSEric Fiselier      _And<
7383359a17bSEric Fiselier          _IsNotSame<_Up, _Tp>,
739a9e65961SEric Fiselier          is_constructible<_Tp, _QualUp>,
740a9e65961SEric Fiselier          is_assignable<_Tp&, _QualUp>
741a9e65961SEric Fiselier      >::value,
742a9e65961SEric Fiselier      _CheckOptionalLikeConstructor<_QualUp>,
743a9e65961SEric Fiselier      __check_tuple_constructor_fail
744a9e65961SEric Fiselier    >;
74517cfc57dSNikolas Klauser
746a9e65961SEric Fiselierpublic:
747a9e65961SEric Fiselier
748a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
749c1bcd4c1SMarshall Clow    _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
750c1bcd4c1SMarshall Clow    _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
751a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
752a9e65961SEric Fiselier
7534e0ea2cfSLouis Dionne    template <class _InPlaceT, class... _Args, class = enable_if_t<
7543359a17bSEric Fiselier          _And<
7553359a17bSEric Fiselier              _IsSame<_InPlaceT, in_place_t>,
75686af6f50SEric Fiselier              is_constructible<value_type, _Args...>
75786af6f50SEric Fiselier            >::value
75886af6f50SEric Fiselier        >
759a9e65961SEric Fiselier    >
760a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
76186af6f50SEric Fiselier    constexpr explicit optional(_InPlaceT, _Args&&... __args)
762a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
763a9e65961SEric Fiselier
7644e0ea2cfSLouis Dionne    template <class _Up, class... _Args, class = enable_if_t<
765a9e65961SEric Fiselier        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
766a9e65961SEric Fiselier    >
767a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
768a9e65961SEric Fiselier    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
769a9e65961SEric Fiselier        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
770a9e65961SEric Fiselier
7714e0ea2cfSLouis Dionne    template <class _Up = value_type, enable_if_t<
772a9e65961SEric Fiselier        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
773a9e65961SEric Fiselier    , int> = 0>
774a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
775a9e65961SEric Fiselier    constexpr optional(_Up&& __v)
776a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
777a9e65961SEric Fiselier
7784e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
779a9e65961SEric Fiselier        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
780a9e65961SEric Fiselier    , int> = 0>
781a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
782a9e65961SEric Fiselier    constexpr explicit optional(_Up&& __v)
783a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
784a9e65961SEric Fiselier
785a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from const optional<_Up>&
7864e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
787a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
788a9e65961SEric Fiselier    , int> = 0>
789a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
79054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
791a9e65961SEric Fiselier    {
792a9e65961SEric Fiselier        this->__construct_from(__v);
793a9e65961SEric Fiselier    }
7944e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
795a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
796a9e65961SEric Fiselier    , int> = 0>
797a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
79854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
799a9e65961SEric Fiselier    {
800a9e65961SEric Fiselier        this->__construct_from(__v);
801a9e65961SEric Fiselier    }
802a9e65961SEric Fiselier
803a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from optional<_Up>&&
8044e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
805a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
806a9e65961SEric Fiselier    , int> = 0>
807a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
80854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
809a9e65961SEric Fiselier    {
810a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__v));
811a9e65961SEric Fiselier    }
8124e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
813a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
814a9e65961SEric Fiselier    , int> = 0>
815a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
81654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
817a9e65961SEric Fiselier    {
818a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__v));
819a9e65961SEric Fiselier    }
820a9e65961SEric Fiselier
82117cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
82217cfc57dSNikolas Klauser  template<class _Fp, class... _Args>
82317cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
82417cfc57dSNikolas Klauser  constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
82517cfc57dSNikolas Klauser      : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
82617cfc57dSNikolas Klauser  }
82717cfc57dSNikolas Klauser#endif
82817cfc57dSNikolas Klauser
829a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
83054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
831a9e65961SEric Fiselier    {
832a9e65961SEric Fiselier        reset();
833a9e65961SEric Fiselier        return *this;
834a9e65961SEric Fiselier    }
835a9e65961SEric Fiselier
836a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
837a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
838a9e65961SEric Fiselier
839a9e65961SEric Fiselier    // LWG2756
840a9e65961SEric Fiselier    template <class _Up = value_type,
8414e0ea2cfSLouis Dionne              class = enable_if_t<
8423359a17bSEric Fiselier                      _And<
8433359a17bSEric Fiselier                          _IsNotSame<__uncvref_t<_Up>, optional>,
8443359a17bSEric Fiselier                          _Or<
845954014a0SMarshall Clow                              _IsNotSame<__uncvref_t<_Up>, value_type>,
8463359a17bSEric Fiselier                              _Not<is_scalar<value_type>>
847015fcffdSEric Fiselier                          >,
848015fcffdSEric Fiselier                          is_constructible<value_type, _Up>,
849015fcffdSEric Fiselier                          is_assignable<value_type&, _Up>
850015fcffdSEric Fiselier                      >::value>
851a9e65961SEric Fiselier             >
852a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
85354644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
854a9e65961SEric Fiselier    operator=(_Up&& __v)
855a9e65961SEric Fiselier    {
856a9e65961SEric Fiselier        if (this->has_value())
857a9e65961SEric Fiselier            this->__get() = _VSTD::forward<_Up>(__v);
858a9e65961SEric Fiselier        else
859a9e65961SEric Fiselier            this->__construct(_VSTD::forward<_Up>(__v));
860a9e65961SEric Fiselier        return *this;
861a9e65961SEric Fiselier    }
862a9e65961SEric Fiselier
863a9e65961SEric Fiselier    // LWG2756
8644e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
865a9e65961SEric Fiselier        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
866a9e65961SEric Fiselier    , int> = 0>
867a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
86854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
869a9e65961SEric Fiselier    operator=(const optional<_Up>& __v)
870a9e65961SEric Fiselier    {
871a9e65961SEric Fiselier        this->__assign_from(__v);
872a9e65961SEric Fiselier        return *this;
873a9e65961SEric Fiselier    }
874a9e65961SEric Fiselier
875a9e65961SEric Fiselier    // LWG2756
8764e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
877a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
878a9e65961SEric Fiselier    , int> = 0>
879a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
88054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
881a9e65961SEric Fiselier    operator=(optional<_Up>&& __v)
882a9e65961SEric Fiselier    {
883a9e65961SEric Fiselier        this->__assign_from(_VSTD::move(__v));
884a9e65961SEric Fiselier        return *this;
885a9e65961SEric Fiselier    }
886a9e65961SEric Fiselier
887a9e65961SEric Fiselier    template <class... _Args,
8884e0ea2cfSLouis Dionne              class = enable_if_t
889a9e65961SEric Fiselier                      <
890a9e65961SEric Fiselier                          is_constructible_v<value_type, _Args...>
891a9e65961SEric Fiselier                      >
892a9e65961SEric Fiselier             >
893a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
89454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
895a9e65961SEric Fiselier    emplace(_Args&&... __args)
896a9e65961SEric Fiselier    {
897a9e65961SEric Fiselier        reset();
898a9e65961SEric Fiselier        this->__construct(_VSTD::forward<_Args>(__args)...);
8995c80f4f6SMarshall Clow        return this->__get();
900a9e65961SEric Fiselier    }
901a9e65961SEric Fiselier
902a9e65961SEric Fiselier    template <class _Up, class... _Args,
9034e0ea2cfSLouis Dionne              class = enable_if_t
904a9e65961SEric Fiselier                      <
905a9e65961SEric Fiselier                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
906a9e65961SEric Fiselier                      >
907a9e65961SEric Fiselier             >
908a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
90954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
910a9e65961SEric Fiselier    emplace(initializer_list<_Up> __il, _Args&&... __args)
911a9e65961SEric Fiselier    {
912a9e65961SEric Fiselier        reset();
913a9e65961SEric Fiselier        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
9145c80f4f6SMarshall Clow        return this->__get();
915a9e65961SEric Fiselier    }
916a9e65961SEric Fiselier
917a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
91854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
919a9e65961SEric Fiselier        noexcept(is_nothrow_move_constructible_v<value_type> &&
920a9e65961SEric Fiselier                 is_nothrow_swappable_v<value_type>)
921a9e65961SEric Fiselier    {
922a9e65961SEric Fiselier        if (this->has_value() == __opt.has_value())
923a9e65961SEric Fiselier        {
924a9e65961SEric Fiselier            using _VSTD::swap;
925a9e65961SEric Fiselier            if (this->has_value())
926a9e65961SEric Fiselier                swap(this->__get(), __opt.__get());
927a9e65961SEric Fiselier        }
928a9e65961SEric Fiselier        else
929a9e65961SEric Fiselier        {
930a9e65961SEric Fiselier            if (this->has_value())
931a9e65961SEric Fiselier            {
932a9e65961SEric Fiselier                __opt.__construct(_VSTD::move(this->__get()));
933a9e65961SEric Fiselier                reset();
934a9e65961SEric Fiselier            }
935a9e65961SEric Fiselier            else
936a9e65961SEric Fiselier            {
937a9e65961SEric Fiselier                this->__construct(_VSTD::move(__opt.__get()));
938a9e65961SEric Fiselier                __opt.reset();
939a9e65961SEric Fiselier            }
940a9e65961SEric Fiselier        }
941a9e65961SEric Fiselier    }
942a9e65961SEric Fiselier
943a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
944a9e65961SEric Fiselier    constexpr
945a9e65961SEric Fiselier    add_pointer_t<value_type const>
946a9e65961SEric Fiselier    operator->() const
947a9e65961SEric Fiselier    {
94896100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
949a9e65961SEric Fiselier        return _VSTD::addressof(this->__get());
950a9e65961SEric Fiselier    }
951a9e65961SEric Fiselier
952a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
953a9e65961SEric Fiselier    constexpr
954a9e65961SEric Fiselier    add_pointer_t<value_type>
955a9e65961SEric Fiselier    operator->()
956a9e65961SEric Fiselier    {
95796100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
958a9e65961SEric Fiselier        return _VSTD::addressof(this->__get());
959a9e65961SEric Fiselier    }
960a9e65961SEric Fiselier
961a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
962a9e65961SEric Fiselier    constexpr
963a9e65961SEric Fiselier    const value_type&
96400044421Szoecarver    operator*() const& noexcept
965a9e65961SEric Fiselier    {
96696100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
967a9e65961SEric Fiselier        return this->__get();
968a9e65961SEric Fiselier    }
969a9e65961SEric Fiselier
970a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
971a9e65961SEric Fiselier    constexpr
972a9e65961SEric Fiselier    value_type&
97300044421Szoecarver    operator*() & noexcept
974a9e65961SEric Fiselier    {
97596100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
976a9e65961SEric Fiselier        return this->__get();
977a9e65961SEric Fiselier    }
978a9e65961SEric Fiselier
979a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
980a9e65961SEric Fiselier    constexpr
981a9e65961SEric Fiselier    value_type&&
98200044421Szoecarver    operator*() && noexcept
983a9e65961SEric Fiselier    {
98496100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
985a9e65961SEric Fiselier        return _VSTD::move(this->__get());
986a9e65961SEric Fiselier    }
987a9e65961SEric Fiselier
988a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
989a9e65961SEric Fiselier    constexpr
990a9e65961SEric Fiselier    const value_type&&
99100044421Szoecarver    operator*() const&& noexcept
992a9e65961SEric Fiselier    {
99396100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
994a9e65961SEric Fiselier        return _VSTD::move(this->__get());
995a9e65961SEric Fiselier    }
996a9e65961SEric Fiselier
997a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
998a9e65961SEric Fiselier    constexpr explicit operator bool() const noexcept { return has_value(); }
999a9e65961SEric Fiselier
1000a9e65961SEric Fiselier    using __base::has_value;
1001a9e65961SEric Fiselier    using __base::__get;
1002a9e65961SEric Fiselier
1003a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10048a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1005a9e65961SEric Fiselier    constexpr value_type const& value() const&
1006a9e65961SEric Fiselier    {
1007a9e65961SEric Fiselier        if (!this->has_value())
1008a9e65961SEric Fiselier            __throw_bad_optional_access();
1009a9e65961SEric Fiselier        return this->__get();
1010a9e65961SEric Fiselier    }
1011a9e65961SEric Fiselier
1012a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10138a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1014a9e65961SEric Fiselier    constexpr value_type& value() &
1015a9e65961SEric Fiselier    {
1016a9e65961SEric Fiselier        if (!this->has_value())
1017a9e65961SEric Fiselier            __throw_bad_optional_access();
1018a9e65961SEric Fiselier        return this->__get();
1019a9e65961SEric Fiselier    }
1020a9e65961SEric Fiselier
1021a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10228a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1023a9e65961SEric Fiselier    constexpr value_type&& value() &&
1024a9e65961SEric Fiselier    {
1025a9e65961SEric Fiselier        if (!this->has_value())
1026a9e65961SEric Fiselier            __throw_bad_optional_access();
1027a9e65961SEric Fiselier        return _VSTD::move(this->__get());
1028a9e65961SEric Fiselier    }
1029a9e65961SEric Fiselier
1030a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10318a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1032a9e65961SEric Fiselier    constexpr value_type const&& value() const&&
1033a9e65961SEric Fiselier    {
1034a9e65961SEric Fiselier        if (!this->has_value())
1035a9e65961SEric Fiselier            __throw_bad_optional_access();
1036a9e65961SEric Fiselier        return _VSTD::move(this->__get());
1037a9e65961SEric Fiselier    }
1038a9e65961SEric Fiselier
1039a9e65961SEric Fiselier    template <class _Up>
1040a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1041a9e65961SEric Fiselier    constexpr value_type value_or(_Up&& __v) const&
1042a9e65961SEric Fiselier    {
1043a9e65961SEric Fiselier        static_assert(is_copy_constructible_v<value_type>,
1044a9e65961SEric Fiselier                      "optional<T>::value_or: T must be copy constructible");
1045a9e65961SEric Fiselier        static_assert(is_convertible_v<_Up, value_type>,
1046a9e65961SEric Fiselier                      "optional<T>::value_or: U must be convertible to T");
1047a9e65961SEric Fiselier        return this->has_value() ? this->__get() :
1048a9e65961SEric Fiselier                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1049a9e65961SEric Fiselier    }
1050a9e65961SEric Fiselier
1051a9e65961SEric Fiselier    template <class _Up>
1052a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1053dd7c68bcSCasey Carter    constexpr value_type value_or(_Up&& __v) &&
1054a9e65961SEric Fiselier    {
1055a9e65961SEric Fiselier        static_assert(is_move_constructible_v<value_type>,
1056a9e65961SEric Fiselier                      "optional<T>::value_or: T must be move constructible");
1057a9e65961SEric Fiselier        static_assert(is_convertible_v<_Up, value_type>,
1058a9e65961SEric Fiselier                      "optional<T>::value_or: U must be convertible to T");
1059a9e65961SEric Fiselier        return this->has_value() ? _VSTD::move(this->__get()) :
1060a9e65961SEric Fiselier                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1061a9e65961SEric Fiselier    }
1062a9e65961SEric Fiselier
106317cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
106417cfc57dSNikolas Klauser  template<class _Func>
1065fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
106617cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) & {
106717cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, value_type&>;
106817cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
106917cfc57dSNikolas Klauser                  "Result of f(value()) must be a specialization of std::optional");
107017cfc57dSNikolas Klauser    if (*this)
107117cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
107217cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
107317cfc57dSNikolas Klauser  }
107417cfc57dSNikolas Klauser
107517cfc57dSNikolas Klauser  template<class _Func>
1076fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
107717cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) const& {
107817cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, const value_type&>;
107917cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
108017cfc57dSNikolas Klauser                  "Result of f(value()) must be a specialization of std::optional");
108117cfc57dSNikolas Klauser    if (*this)
108217cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
108317cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
108417cfc57dSNikolas Klauser  }
108517cfc57dSNikolas Klauser
108617cfc57dSNikolas Klauser  template<class _Func>
1087fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
108817cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) && {
108917cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, value_type&&>;
109017cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
109117cfc57dSNikolas Klauser                  "Result of f(std::move(value())) must be a specialization of std::optional");
109217cfc57dSNikolas Klauser    if (*this)
109317cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
109417cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
109517cfc57dSNikolas Klauser  }
109617cfc57dSNikolas Klauser
109717cfc57dSNikolas Klauser  template<class _Func>
109817cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
109917cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) const&& {
110017cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, const value_type&&>;
110117cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
110217cfc57dSNikolas Klauser                  "Result of f(std::move(value())) must be a specialization of std::optional");
110317cfc57dSNikolas Klauser    if (*this)
110417cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
110517cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
110617cfc57dSNikolas Klauser  }
110717cfc57dSNikolas Klauser
110817cfc57dSNikolas Klauser  template<class _Func>
1109fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
111017cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) & {
111117cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
111217cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
111317cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
111417cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::in_place_t");
111517cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
111617cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::nullopt_t");
111717cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
111817cfc57dSNikolas Klauser    if (*this)
111917cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
112017cfc57dSNikolas Klauser    return optional<_Up>();
112117cfc57dSNikolas Klauser  }
112217cfc57dSNikolas Klauser
112317cfc57dSNikolas Klauser  template<class _Func>
1124fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
112517cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) const& {
112617cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
112717cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
112817cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
112917cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::in_place_t");
113017cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
113117cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::nullopt_t");
113217cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
113317cfc57dSNikolas Klauser    if (*this)
113417cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
113517cfc57dSNikolas Klauser    return optional<_Up>();
113617cfc57dSNikolas Klauser  }
113717cfc57dSNikolas Klauser
113817cfc57dSNikolas Klauser  template<class _Func>
1139fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
114017cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) && {
114117cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
114217cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
114317cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
114417cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::in_place_t");
114517cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
114617cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::nullopt_t");
114717cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
114817cfc57dSNikolas Klauser    if (*this)
114917cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
115017cfc57dSNikolas Klauser    return optional<_Up>();
115117cfc57dSNikolas Klauser  }
115217cfc57dSNikolas Klauser
115317cfc57dSNikolas Klauser  template<class _Func>
1154fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
115517cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) const&& {
115617cfc57dSNikolas Klauser    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
115717cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
115817cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
115917cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::in_place_t");
116017cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
116117cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::nullopt_t");
116217cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
116317cfc57dSNikolas Klauser    if (*this)
116417cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
116517cfc57dSNikolas Klauser    return optional<_Up>();
116617cfc57dSNikolas Klauser  }
116717cfc57dSNikolas Klauser
116817cfc57dSNikolas Klauser  template<invocable _Func>
116917cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
117017cfc57dSNikolas Klauser  constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
117117cfc57dSNikolas Klauser    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
117217cfc57dSNikolas Klauser                  "Result of f() should be the same type as this optional");
117317cfc57dSNikolas Klauser    if (*this)
117417cfc57dSNikolas Klauser      return *this;
117517cfc57dSNikolas Klauser    return _VSTD::forward<_Func>(__f)();
117617cfc57dSNikolas Klauser  }
117717cfc57dSNikolas Klauser
117817cfc57dSNikolas Klauser  template<invocable _Func>
117917cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
118017cfc57dSNikolas Klauser  constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
118117cfc57dSNikolas Klauser    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
118217cfc57dSNikolas Klauser                  "Result of f() should be the same type as this optional");
118317cfc57dSNikolas Klauser    if (*this)
118417cfc57dSNikolas Klauser      return _VSTD::move(*this);
118517cfc57dSNikolas Klauser    return _VSTD::forward<_Func>(__f)();
118617cfc57dSNikolas Klauser  }
118717cfc57dSNikolas Klauser#endif // _LIBCPP_STD_VER > 20
118817cfc57dSNikolas Klauser
1189a9e65961SEric Fiselier    using __base::reset;
1190a9e65961SEric Fiselier};
1191a9e65961SEric Fiselier
119201666904SLouis Dionne#if _LIBCPP_STD_VER >= 17
1193a8f1a715SArthur O'Dwyertemplate<class _Tp>
1194a8f1a715SArthur O'Dwyer    optional(_Tp) -> optional<_Tp>;
1195f35b4bc3SMarshall Clow#endif
1196f35b4bc3SMarshall Clow
1197a9e65961SEric Fiselier// Comparisons between optionals
1198dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1199a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12004e0ea2cfSLouis Dionneenable_if_t<
1201ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1202ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1203a9e65961SEric Fiselier    bool
1204a9e65961SEric Fiselier>
1205dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const optional<_Up>& __y)
1206a9e65961SEric Fiselier{
1207a9e65961SEric Fiselier    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1208a9e65961SEric Fiselier        return false;
1209a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1210a9e65961SEric Fiselier        return true;
1211a9e65961SEric Fiselier    return *__x == *__y;
1212a9e65961SEric Fiselier}
1213a9e65961SEric Fiselier
1214dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1215a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12164e0ea2cfSLouis Dionneenable_if_t<
1217ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1218ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1219a9e65961SEric Fiselier    bool
1220a9e65961SEric Fiselier>
1221dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
1222a9e65961SEric Fiselier{
1223a9e65961SEric Fiselier    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1224a9e65961SEric Fiselier        return true;
1225a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1226a9e65961SEric Fiselier        return false;
1227a9e65961SEric Fiselier    return *__x != *__y;
1228a9e65961SEric Fiselier}
1229a9e65961SEric Fiselier
1230dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1231a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12324e0ea2cfSLouis Dionneenable_if_t<
1233ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1234ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1235a9e65961SEric Fiselier    bool
1236a9e65961SEric Fiselier>
1237dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const optional<_Up>& __y)
1238a9e65961SEric Fiselier{
1239a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1240a9e65961SEric Fiselier        return false;
1241a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1242a9e65961SEric Fiselier        return true;
1243a9e65961SEric Fiselier    return *__x < *__y;
1244a9e65961SEric Fiselier}
1245a9e65961SEric Fiselier
1246dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1247a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12484e0ea2cfSLouis Dionneenable_if_t<
1249ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1250ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1251a9e65961SEric Fiselier    bool
1252a9e65961SEric Fiselier>
1253dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const optional<_Up>& __y)
1254a9e65961SEric Fiselier{
1255a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1256a9e65961SEric Fiselier        return false;
1257a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1258a9e65961SEric Fiselier        return true;
1259a9e65961SEric Fiselier    return *__x > *__y;
1260a9e65961SEric Fiselier}
1261a9e65961SEric Fiselier
1262dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1263a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12644e0ea2cfSLouis Dionneenable_if_t<
1265ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1266ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1267a9e65961SEric Fiselier    bool
1268a9e65961SEric Fiselier>
1269dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
1270a9e65961SEric Fiselier{
1271a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1272a9e65961SEric Fiselier        return true;
1273a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1274a9e65961SEric Fiselier        return false;
1275a9e65961SEric Fiselier    return *__x <= *__y;
1276a9e65961SEric Fiselier}
1277a9e65961SEric Fiselier
1278dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1279a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12804e0ea2cfSLouis Dionneenable_if_t<
1281ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1282ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1283a9e65961SEric Fiselier    bool
1284a9e65961SEric Fiselier>
1285dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
1286a9e65961SEric Fiselier{
1287a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1288a9e65961SEric Fiselier        return true;
1289a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1290a9e65961SEric Fiselier        return false;
1291a9e65961SEric Fiselier    return *__x >= *__y;
1292a9e65961SEric Fiselier}
1293a9e65961SEric Fiselier
1294a9e65961SEric Fiselier// Comparisons with nullopt
1295a9e65961SEric Fiseliertemplate <class _Tp>
1296a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1297a9e65961SEric Fiselierbool
1298a9e65961SEric Fiselieroperator==(const optional<_Tp>& __x, nullopt_t) noexcept
1299a9e65961SEric Fiselier{
1300a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1301a9e65961SEric Fiselier}
1302a9e65961SEric Fiselier
1303a9e65961SEric Fiseliertemplate <class _Tp>
1304a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1305a9e65961SEric Fiselierbool
1306a9e65961SEric Fiselieroperator==(nullopt_t, const optional<_Tp>& __x) noexcept
1307a9e65961SEric Fiselier{
1308a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1309a9e65961SEric Fiselier}
1310a9e65961SEric Fiselier
1311a9e65961SEric Fiseliertemplate <class _Tp>
1312a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1313a9e65961SEric Fiselierbool
1314a9e65961SEric Fiselieroperator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1315a9e65961SEric Fiselier{
1316a9e65961SEric Fiselier    return static_cast<bool>(__x);
1317a9e65961SEric Fiselier}
1318a9e65961SEric Fiselier
1319a9e65961SEric Fiseliertemplate <class _Tp>
1320a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1321a9e65961SEric Fiselierbool
1322a9e65961SEric Fiselieroperator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1323a9e65961SEric Fiselier{
1324a9e65961SEric Fiselier    return static_cast<bool>(__x);
1325a9e65961SEric Fiselier}
1326a9e65961SEric Fiselier
1327a9e65961SEric Fiseliertemplate <class _Tp>
1328a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1329a9e65961SEric Fiselierbool
1330a9e65961SEric Fiselieroperator<(const optional<_Tp>&, nullopt_t) noexcept
1331a9e65961SEric Fiselier{
1332a9e65961SEric Fiselier    return false;
1333a9e65961SEric Fiselier}
1334a9e65961SEric Fiselier
1335a9e65961SEric Fiseliertemplate <class _Tp>
1336a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1337a9e65961SEric Fiselierbool
1338a9e65961SEric Fiselieroperator<(nullopt_t, const optional<_Tp>& __x) noexcept
1339a9e65961SEric Fiselier{
1340a9e65961SEric Fiselier    return static_cast<bool>(__x);
1341a9e65961SEric Fiselier}
1342a9e65961SEric Fiselier
1343a9e65961SEric Fiseliertemplate <class _Tp>
1344a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1345a9e65961SEric Fiselierbool
1346a9e65961SEric Fiselieroperator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1347a9e65961SEric Fiselier{
1348a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1349a9e65961SEric Fiselier}
1350a9e65961SEric Fiselier
1351a9e65961SEric Fiseliertemplate <class _Tp>
1352a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1353a9e65961SEric Fiselierbool
1354fd838227SEric Fiselieroperator<=(nullopt_t, const optional<_Tp>&) noexcept
1355a9e65961SEric Fiselier{
1356a9e65961SEric Fiselier    return true;
1357a9e65961SEric Fiselier}
1358a9e65961SEric Fiselier
1359a9e65961SEric Fiseliertemplate <class _Tp>
1360a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1361a9e65961SEric Fiselierbool
1362a9e65961SEric Fiselieroperator>(const optional<_Tp>& __x, nullopt_t) noexcept
1363a9e65961SEric Fiselier{
1364a9e65961SEric Fiselier    return static_cast<bool>(__x);
1365a9e65961SEric Fiselier}
1366a9e65961SEric Fiselier
1367a9e65961SEric Fiseliertemplate <class _Tp>
1368a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1369a9e65961SEric Fiselierbool
1370fd838227SEric Fiselieroperator>(nullopt_t, const optional<_Tp>&) noexcept
1371a9e65961SEric Fiselier{
1372a9e65961SEric Fiselier    return false;
1373a9e65961SEric Fiselier}
1374a9e65961SEric Fiselier
1375a9e65961SEric Fiseliertemplate <class _Tp>
1376a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1377a9e65961SEric Fiselierbool
1378a9e65961SEric Fiselieroperator>=(const optional<_Tp>&, nullopt_t) noexcept
1379a9e65961SEric Fiselier{
1380a9e65961SEric Fiselier    return true;
1381a9e65961SEric Fiselier}
1382a9e65961SEric Fiselier
1383a9e65961SEric Fiseliertemplate <class _Tp>
1384a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1385a9e65961SEric Fiselierbool
1386a9e65961SEric Fiselieroperator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1387a9e65961SEric Fiselier{
1388a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1389a9e65961SEric Fiselier}
1390a9e65961SEric Fiselier
1391a9e65961SEric Fiselier// Comparisons with T
1392dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1393a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
13944e0ea2cfSLouis Dionneenable_if_t<
1395ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1396ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1397a9e65961SEric Fiselier    bool
1398a9e65961SEric Fiselier>
1399dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const _Up& __v)
1400a9e65961SEric Fiselier{
1401a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x == __v : false;
1402a9e65961SEric Fiselier}
1403a9e65961SEric Fiselier
1404dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1405a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14064e0ea2cfSLouis Dionneenable_if_t<
1407ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1408ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1409a9e65961SEric Fiselier    bool
1410a9e65961SEric Fiselier>
1411dc808af3SEric Fiselieroperator==(const _Tp& __v, const optional<_Up>& __x)
1412a9e65961SEric Fiselier{
1413a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v == *__x : false;
1414a9e65961SEric Fiselier}
1415a9e65961SEric Fiselier
1416dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1417a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14184e0ea2cfSLouis Dionneenable_if_t<
1419ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1420ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1421a9e65961SEric Fiselier    bool
1422a9e65961SEric Fiselier>
1423dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const _Up& __v)
1424a9e65961SEric Fiselier{
1425a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x != __v : true;
1426a9e65961SEric Fiselier}
1427a9e65961SEric Fiselier
1428dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1429a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14304e0ea2cfSLouis Dionneenable_if_t<
1431ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1432ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1433a9e65961SEric Fiselier    bool
1434a9e65961SEric Fiselier>
1435dc808af3SEric Fiselieroperator!=(const _Tp& __v, const optional<_Up>& __x)
1436a9e65961SEric Fiselier{
1437a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v != *__x : true;
1438a9e65961SEric Fiselier}
1439a9e65961SEric Fiselier
1440dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1441a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14424e0ea2cfSLouis Dionneenable_if_t<
1443ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1444ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1445a9e65961SEric Fiselier    bool
1446a9e65961SEric Fiselier>
1447dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const _Up& __v)
1448a9e65961SEric Fiselier{
1449a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x < __v : true;
1450a9e65961SEric Fiselier}
1451a9e65961SEric Fiselier
1452dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1453a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14544e0ea2cfSLouis Dionneenable_if_t<
1455ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1456ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1457a9e65961SEric Fiselier    bool
1458a9e65961SEric Fiselier>
1459dc808af3SEric Fiselieroperator<(const _Tp& __v, const optional<_Up>& __x)
1460a9e65961SEric Fiselier{
1461a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v < *__x : false;
1462a9e65961SEric Fiselier}
1463a9e65961SEric Fiselier
1464dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1465a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14664e0ea2cfSLouis Dionneenable_if_t<
1467ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1468ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1469a9e65961SEric Fiselier    bool
1470a9e65961SEric Fiselier>
1471dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const _Up& __v)
1472a9e65961SEric Fiselier{
1473a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x <= __v : true;
1474a9e65961SEric Fiselier}
1475a9e65961SEric Fiselier
1476dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1477a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14784e0ea2cfSLouis Dionneenable_if_t<
1479ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1480ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1481a9e65961SEric Fiselier    bool
1482a9e65961SEric Fiselier>
1483dc808af3SEric Fiselieroperator<=(const _Tp& __v, const optional<_Up>& __x)
1484a9e65961SEric Fiselier{
1485a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v <= *__x : false;
1486a9e65961SEric Fiselier}
1487a9e65961SEric Fiselier
1488dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1489a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14904e0ea2cfSLouis Dionneenable_if_t<
1491ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1492ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1493a9e65961SEric Fiselier    bool
1494a9e65961SEric Fiselier>
1495dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const _Up& __v)
1496a9e65961SEric Fiselier{
1497a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x > __v : false;
1498a9e65961SEric Fiselier}
1499a9e65961SEric Fiselier
1500dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1501a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
15024e0ea2cfSLouis Dionneenable_if_t<
1503ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1504ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1505a9e65961SEric Fiselier    bool
1506a9e65961SEric Fiselier>
1507dc808af3SEric Fiselieroperator>(const _Tp& __v, const optional<_Up>& __x)
1508a9e65961SEric Fiselier{
1509a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v > *__x : true;
1510a9e65961SEric Fiselier}
1511a9e65961SEric Fiselier
1512dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1513a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
15144e0ea2cfSLouis Dionneenable_if_t<
1515ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1516ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1517a9e65961SEric Fiselier    bool
1518a9e65961SEric Fiselier>
1519dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const _Up& __v)
1520a9e65961SEric Fiselier{
1521a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x >= __v : false;
1522a9e65961SEric Fiselier}
1523a9e65961SEric Fiselier
1524dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1525a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
15264e0ea2cfSLouis Dionneenable_if_t<
1527ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1528ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1529a9e65961SEric Fiselier    bool
1530a9e65961SEric Fiselier>
1531dc808af3SEric Fiselieroperator>=(const _Tp& __v, const optional<_Up>& __x)
1532a9e65961SEric Fiselier{
1533a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v >= *__x : true;
1534a9e65961SEric Fiselier}
1535a9e65961SEric Fiselier
1536a9e65961SEric Fiselier
1537a9e65961SEric Fiseliertemplate <class _Tp>
153854644993SChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
15394e0ea2cfSLouis Dionneenable_if_t<
1540a9e65961SEric Fiselier    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1541a9e65961SEric Fiselier    void
1542a9e65961SEric Fiselier>
1543a9e65961SEric Fiselierswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1544a9e65961SEric Fiselier{
1545a9e65961SEric Fiselier    __x.swap(__y);
1546a9e65961SEric Fiselier}
1547a9e65961SEric Fiselier
1548a9e65961SEric Fiseliertemplate <class _Tp>
1549a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1550a9e65961SEric Fiselieroptional<decay_t<_Tp>> make_optional(_Tp&& __v)
1551a9e65961SEric Fiselier{
1552a9e65961SEric Fiselier    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1553a9e65961SEric Fiselier}
1554a9e65961SEric Fiselier
1555a9e65961SEric Fiseliertemplate <class _Tp, class... _Args>
1556a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1557a9e65961SEric Fiselieroptional<_Tp> make_optional(_Args&&... __args)
1558a9e65961SEric Fiselier{
1559a9e65961SEric Fiselier    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1560a9e65961SEric Fiselier}
1561a9e65961SEric Fiselier
1562a9e65961SEric Fiseliertemplate <class _Tp, class _Up, class... _Args>
1563a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1564a9e65961SEric Fiselieroptional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
1565a9e65961SEric Fiselier{
1566a9e65961SEric Fiselier    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1567a9e65961SEric Fiselier}
1568a9e65961SEric Fiselier
1569a9e65961SEric Fiseliertemplate <class _Tp>
1570f9127593SEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash<
1571f9127593SEric Fiselier    __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1572f9127593SEric Fiselier>
1573a9e65961SEric Fiselier{
1574dc066888SArthur O'Dwyer#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1575dc066888SArthur O'Dwyer    _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1576dc066888SArthur O'Dwyer    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t        result_type;
1577dc066888SArthur O'Dwyer#endif
1578a9e65961SEric Fiselier
1579a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1580dc066888SArthur O'Dwyer    size_t operator()(const optional<_Tp>& __opt) const
1581a9e65961SEric Fiselier    {
1582f9127593SEric Fiselier        return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
1583a9e65961SEric Fiselier    }
1584a9e65961SEric Fiselier};
1585a9e65961SEric Fiselier
1586a9e65961SEric Fiselier_LIBCPP_END_NAMESPACE_STD
1587a9e65961SEric Fiselier
1588a9e65961SEric Fiselier#endif // _LIBCPP_STD_VER > 14
1589a9e65961SEric Fiselier
1590a9e65961SEric Fiselier#endif // _LIBCPP_OPTIONAL
1591