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>
96a9e65961SEric Fiselier      constexpr EXPLICIT optional(U &&);
97a9e65961SEric Fiselier    template <class U>
9854644993SChristopher Di Bella      EXPLICIT optional(const optional<U> &);   // constexpr in C++20
99a9e65961SEric Fiselier    template <class U>
10054644993SChristopher Di Bella      EXPLICIT 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>
165*faef447eSNikolas Klauser#include <__functional/hash.h>
166*faef447eSNikolas Klauser#include <__functional/invoke.h>
167*faef447eSNikolas Klauser#include <__functional/unary_function.h>
168*faef447eSNikolas Klauser#include <__memory/construct_at.h>
169*faef447eSNikolas Klauser#include <__tuple>
170*faef447eSNikolas Klauser#include <__utility/forward.h>
17152915d78SNikolas Klauser#include <__utility/in_place.h>
172*faef447eSNikolas Klauser#include <__utility/move.h>
17352915d78SNikolas Klauser#include <__utility/swap.h>
1742d0f1fa4SArthur O'Dwyer#include <compare>
175*faef447eSNikolas Klauser#include <functional> // TODO: Remove this include
176a9e65961SEric Fiselier#include <initializer_list>
177a9e65961SEric Fiselier#include <new>
178a9e65961SEric Fiselier#include <stdexcept>
179a9e65961SEric Fiselier#include <type_traits>
180f56972e2SMarshall Clow#include <version>
181a9e65961SEric Fiselier
182169a66eaSNikolas Klauser// TODO: remove these headers
183169a66eaSNikolas Klauser#include <__memory/allocator_arg_t.h>
184169a66eaSNikolas Klauser#include <__memory/uses_allocator.h>
185169a66eaSNikolas Klauser#include <typeinfo>
186169a66eaSNikolas Klauser
187a9e65961SEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
188a9e65961SEric Fiselier#  pragma GCC system_header
189a9e65961SEric Fiselier#endif
190a9e65961SEric Fiselier
191a9e65961SEric Fiseliernamespace std  // purposefully not using versioning namespace
192a9e65961SEric Fiselier{
193a9e65961SEric Fiselier
1948a063df1SLouis Dionneclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
195e29b1ed5SMarshall Clow    : public exception
196a9e65961SEric Fiselier{
197a9e65961SEric Fiselierpublic:
198a9e65961SEric Fiselier    // Get the key function ~bad_optional_access() into the dylib
1996a1d0785SMarshall Clow    virtual ~bad_optional_access() _NOEXCEPT;
200e29b1ed5SMarshall Clow    virtual const char* what() const _NOEXCEPT;
201a9e65961SEric Fiselier};
202a9e65961SEric Fiselier
203d2b0df35SNikolas Klauser} // namespace std
204a9e65961SEric Fiselier
205a9e65961SEric Fiselier#if _LIBCPP_STD_VER > 14
206a9e65961SEric Fiselier
207a9e65961SEric Fiselier_LIBCPP_BEGIN_NAMESPACE_STD
208a9e65961SEric Fiselier
209a9e65961SEric Fiselier_LIBCPP_NORETURN
210a9e65961SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
2118a063df1SLouis Dionne_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
212a9e65961SEric Fiseliervoid __throw_bad_optional_access() {
213a9e65961SEric Fiselier#ifndef _LIBCPP_NO_EXCEPTIONS
214a9e65961SEric Fiselier        throw bad_optional_access();
215a9e65961SEric Fiselier#else
216a9e65961SEric Fiselier        _VSTD::abort();
217a9e65961SEric Fiselier#endif
218a9e65961SEric Fiselier}
219a9e65961SEric Fiselier
220a9e65961SEric Fiselierstruct nullopt_t
221a9e65961SEric Fiselier{
222a9e65961SEric Fiselier    struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
223a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
224a9e65961SEric Fiselier};
225a9e65961SEric Fiselier
226cb793e1aSLouis Dionneinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
227a9e65961SEric Fiselier
22817cfc57dSNikolas Klauserstruct __optional_construct_from_invoke_tag {};
22917cfc57dSNikolas Klauser
230a9e65961SEric Fiseliertemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
231a9e65961SEric Fiselierstruct __optional_destruct_base;
232a9e65961SEric Fiselier
233a9e65961SEric Fiseliertemplate <class _Tp>
234a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, false>
235a9e65961SEric Fiselier{
236a9e65961SEric Fiselier    typedef _Tp value_type;
237a9e65961SEric Fiselier    static_assert(is_object_v<value_type>,
238a9e65961SEric Fiselier        "instantiation of optional with a non-object type is undefined behavior");
239a9e65961SEric Fiselier    union
240a9e65961SEric Fiselier    {
241a9e65961SEric Fiselier        char __null_state_;
242a9e65961SEric Fiselier        value_type __val_;
243a9e65961SEric Fiselier    };
244a9e65961SEric Fiselier    bool __engaged_;
245a9e65961SEric Fiselier
246a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
24754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
248a9e65961SEric Fiselier    {
249a9e65961SEric Fiselier        if (__engaged_)
250a9e65961SEric Fiselier            __val_.~value_type();
251a9e65961SEric Fiselier    }
252a9e65961SEric Fiselier
253a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
254a9e65961SEric Fiselier    constexpr __optional_destruct_base() noexcept
255a9e65961SEric Fiselier        :  __null_state_(),
256a9e65961SEric Fiselier           __engaged_(false) {}
257a9e65961SEric Fiselier
258a9e65961SEric Fiselier    template <class... _Args>
259a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
260a9e65961SEric Fiselier    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
261a9e65961SEric Fiselier        :  __val_(_VSTD::forward<_Args>(__args)...),
262a9e65961SEric Fiselier           __engaged_(true) {}
263a9e65961SEric Fiselier
26417cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
26517cfc57dSNikolas Klauser  template <class _Fp, class... _Args>
26617cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
26717cfc57dSNikolas Klauser  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
26817cfc57dSNikolas Klauser      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
26917cfc57dSNikolas Klauser#endif
27017cfc57dSNikolas Klauser
271a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
27254644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
273a9e65961SEric Fiselier    {
274a9e65961SEric Fiselier        if (__engaged_)
275a9e65961SEric Fiselier        {
276a9e65961SEric Fiselier            __val_.~value_type();
277a9e65961SEric Fiselier            __engaged_ = false;
278a9e65961SEric Fiselier        }
279a9e65961SEric Fiselier    }
280a9e65961SEric Fiselier};
281a9e65961SEric Fiselier
282a9e65961SEric Fiseliertemplate <class _Tp>
283a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, true>
284a9e65961SEric Fiselier{
285a9e65961SEric Fiselier    typedef _Tp value_type;
286a9e65961SEric Fiselier    static_assert(is_object_v<value_type>,
287a9e65961SEric Fiselier        "instantiation of optional with a non-object type is undefined behavior");
288a9e65961SEric Fiselier    union
289a9e65961SEric Fiselier    {
290a9e65961SEric Fiselier        char __null_state_;
291a9e65961SEric Fiselier        value_type __val_;
292a9e65961SEric Fiselier    };
293a9e65961SEric Fiselier    bool __engaged_;
294a9e65961SEric Fiselier
295a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
296a9e65961SEric Fiselier    constexpr __optional_destruct_base() noexcept
297a9e65961SEric Fiselier        :  __null_state_(),
298a9e65961SEric Fiselier           __engaged_(false) {}
299a9e65961SEric Fiselier
300a9e65961SEric Fiselier    template <class... _Args>
301a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
302a9e65961SEric Fiselier    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
303a9e65961SEric Fiselier        :  __val_(_VSTD::forward<_Args>(__args)...),
304a9e65961SEric Fiselier           __engaged_(true) {}
305a9e65961SEric Fiselier
30617cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
30717cfc57dSNikolas Klauser  template <class _Fp, class... _Args>
30817cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
30917cfc57dSNikolas Klauser  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
31017cfc57dSNikolas Klauser      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
31117cfc57dSNikolas Klauser#endif
31217cfc57dSNikolas Klauser
313a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
31454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
315a9e65961SEric Fiselier    {
316a9e65961SEric Fiselier        if (__engaged_)
317a9e65961SEric Fiselier        {
318a9e65961SEric Fiselier            __engaged_ = false;
319a9e65961SEric Fiselier        }
320a9e65961SEric Fiselier    }
321a9e65961SEric Fiselier};
322a9e65961SEric Fiselier
323a9e65961SEric Fiseliertemplate <class _Tp, bool = is_reference<_Tp>::value>
324a9e65961SEric Fiselierstruct __optional_storage_base : __optional_destruct_base<_Tp>
325a9e65961SEric Fiselier{
326a9e65961SEric Fiselier    using __base = __optional_destruct_base<_Tp>;
327a9e65961SEric Fiselier    using value_type = _Tp;
328a9e65961SEric Fiselier    using __base::__base;
329a9e65961SEric Fiselier
330a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
331a9e65961SEric Fiselier    constexpr bool has_value() const noexcept
332a9e65961SEric Fiselier    {
333a9e65961SEric Fiselier        return this->__engaged_;
334a9e65961SEric Fiselier    }
335a9e65961SEric Fiselier
336a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
337a9e65961SEric Fiselier    constexpr value_type& __get() & noexcept
338a9e65961SEric Fiselier    {
339a9e65961SEric Fiselier        return this->__val_;
340a9e65961SEric Fiselier    }
341a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
342a9e65961SEric Fiselier    constexpr const value_type& __get() const& noexcept
343a9e65961SEric Fiselier    {
344a9e65961SEric Fiselier        return this->__val_;
345a9e65961SEric Fiselier    }
346a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
347a9e65961SEric Fiselier    constexpr value_type&& __get() && noexcept
348a9e65961SEric Fiselier    {
349a9e65961SEric Fiselier        return _VSTD::move(this->__val_);
350a9e65961SEric Fiselier    }
351a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
352a9e65961SEric Fiselier    constexpr const value_type&& __get() const&& noexcept
353a9e65961SEric Fiselier    {
354a9e65961SEric Fiselier        return _VSTD::move(this->__val_);
355a9e65961SEric Fiselier    }
356a9e65961SEric Fiselier
357a9e65961SEric Fiselier    template <class... _Args>
358a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
35954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
360a9e65961SEric Fiselier    {
361a9e65961SEric Fiselier        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
36254644993SChristopher Di Bella#if _LIBCPP_STD_VER > 17
36354644993SChristopher Di Bella        _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
36454644993SChristopher Di Bella#else
365a9e65961SEric Fiselier        ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
36654644993SChristopher Di Bella#endif
367a9e65961SEric Fiselier        this->__engaged_ = true;
368a9e65961SEric Fiselier    }
369a9e65961SEric Fiselier
370a9e65961SEric Fiselier    template <class _That>
371a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
37254644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
373a9e65961SEric Fiselier    {
374a9e65961SEric Fiselier        if (__opt.has_value())
375a9e65961SEric Fiselier            __construct(_VSTD::forward<_That>(__opt).__get());
376a9e65961SEric Fiselier    }
377a9e65961SEric Fiselier
378a9e65961SEric Fiselier    template <class _That>
379a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
38054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
381a9e65961SEric Fiselier    {
382a9e65961SEric Fiselier        if (this->__engaged_ == __opt.has_value())
383a9e65961SEric Fiselier        {
384a9e65961SEric Fiselier            if (this->__engaged_)
385a9e65961SEric Fiselier                this->__val_ = _VSTD::forward<_That>(__opt).__get();
386a9e65961SEric Fiselier        }
387a9e65961SEric Fiselier        else
388a9e65961SEric Fiselier        {
389a9e65961SEric Fiselier            if (this->__engaged_)
390a9e65961SEric Fiselier                this->reset();
391a9e65961SEric Fiselier            else
392a9e65961SEric Fiselier                __construct(_VSTD::forward<_That>(__opt).__get());
393a9e65961SEric Fiselier        }
394a9e65961SEric Fiselier    }
395a9e65961SEric Fiselier};
396a9e65961SEric Fiselier
397a9e65961SEric Fiselier// optional<T&> is currently required ill-formed, however it may to be in the
398a9e65961SEric Fiselier// future. For this reason it has already been implemented to ensure we can
399a9e65961SEric Fiselier// make the change in an ABI compatible manner.
400a9e65961SEric Fiseliertemplate <class _Tp>
401a9e65961SEric Fiselierstruct __optional_storage_base<_Tp, true>
402a9e65961SEric Fiselier{
403a9e65961SEric Fiselier    using value_type = _Tp;
404a9e65961SEric Fiselier    using __raw_type = remove_reference_t<_Tp>;
405a9e65961SEric Fiselier    __raw_type* __value_;
406a9e65961SEric Fiselier
407a9e65961SEric Fiselier    template <class _Up>
408a9e65961SEric Fiselier    static constexpr bool __can_bind_reference() {
409a9e65961SEric Fiselier        using _RawUp = typename remove_reference<_Up>::type;
410a9e65961SEric Fiselier        using _UpPtr = _RawUp*;
411a9e65961SEric Fiselier        using _RawTp = typename remove_reference<_Tp>::type;
412a9e65961SEric Fiselier        using _TpPtr = _RawTp*;
413a9e65961SEric Fiselier        using _CheckLValueArg = integral_constant<bool,
414a9e65961SEric Fiselier            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
415a9e65961SEric Fiselier        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
416a9e65961SEric Fiselier        ||  is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
417a9e65961SEric Fiselier        >;
418a9e65961SEric Fiselier        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
419a9e65961SEric Fiselier            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
420a9e65961SEric Fiselier                is_convertible<_UpPtr, _TpPtr>::value);
421a9e65961SEric Fiselier    }
422a9e65961SEric Fiselier
423a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
424a9e65961SEric Fiselier    constexpr __optional_storage_base() noexcept
425a9e65961SEric Fiselier        :  __value_(nullptr) {}
426a9e65961SEric Fiselier
427a9e65961SEric Fiselier    template <class _UArg>
428a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
429a9e65961SEric Fiselier    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
430a9e65961SEric Fiselier        :  __value_(_VSTD::addressof(__uarg))
431a9e65961SEric Fiselier    {
432a9e65961SEric Fiselier      static_assert(__can_bind_reference<_UArg>(),
433a9e65961SEric Fiselier        "Attempted to construct a reference element in tuple from a "
434a9e65961SEric Fiselier        "possible temporary");
435a9e65961SEric Fiselier    }
436a9e65961SEric Fiselier
437a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
43854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
439a9e65961SEric Fiselier
440a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
441a9e65961SEric Fiselier    constexpr bool has_value() const noexcept
442a9e65961SEric Fiselier      { return __value_ != nullptr; }
443a9e65961SEric Fiselier
444a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
445a9e65961SEric Fiselier    constexpr value_type& __get() const& noexcept
446a9e65961SEric Fiselier      { return *__value_; }
447a9e65961SEric Fiselier
448a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
449a9e65961SEric Fiselier    constexpr value_type&& __get() const&& noexcept
450a9e65961SEric Fiselier      { return _VSTD::forward<value_type>(*__value_); }
451a9e65961SEric Fiselier
452a9e65961SEric Fiselier    template <class _UArg>
453a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
45454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
455a9e65961SEric Fiselier    {
456a9e65961SEric Fiselier        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
457a9e65961SEric Fiselier        static_assert(__can_bind_reference<_UArg>(),
458a9e65961SEric Fiselier            "Attempted to construct a reference element in tuple from a "
459a9e65961SEric Fiselier            "possible temporary");
460a9e65961SEric Fiselier        __value_ = _VSTD::addressof(__val);
461a9e65961SEric Fiselier    }
462a9e65961SEric Fiselier
463a9e65961SEric Fiselier    template <class _That>
464a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
46554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
466a9e65961SEric Fiselier    {
467a9e65961SEric Fiselier        if (__opt.has_value())
468a9e65961SEric Fiselier            __construct(_VSTD::forward<_That>(__opt).__get());
469a9e65961SEric Fiselier    }
470a9e65961SEric Fiselier
471a9e65961SEric Fiselier    template <class _That>
472a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
47354644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
474a9e65961SEric Fiselier    {
475a9e65961SEric Fiselier        if (has_value() == __opt.has_value())
476a9e65961SEric Fiselier        {
477a9e65961SEric Fiselier            if (has_value())
478a9e65961SEric Fiselier                *__value_ = _VSTD::forward<_That>(__opt).__get();
479a9e65961SEric Fiselier        }
480a9e65961SEric Fiselier        else
481a9e65961SEric Fiselier        {
482a9e65961SEric Fiselier            if (has_value())
483a9e65961SEric Fiselier                reset();
484a9e65961SEric Fiselier            else
485a9e65961SEric Fiselier                __construct(_VSTD::forward<_That>(__opt).__get());
486a9e65961SEric Fiselier        }
487a9e65961SEric Fiselier    }
488a9e65961SEric Fiselier};
489a9e65961SEric Fiselier
490f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
491f2d571c8SCasey Carterstruct __optional_copy_base : __optional_storage_base<_Tp>
492a9e65961SEric Fiselier{
493a9e65961SEric Fiselier    using __optional_storage_base<_Tp>::__optional_storage_base;
494a9e65961SEric Fiselier};
495a9e65961SEric Fiselier
496a9e65961SEric Fiseliertemplate <class _Tp>
497f2d571c8SCasey Carterstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
498a9e65961SEric Fiselier{
499a9e65961SEric Fiselier    using __optional_storage_base<_Tp>::__optional_storage_base;
500a9e65961SEric Fiselier
501a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
502f2d571c8SCasey Carter    __optional_copy_base() = default;
503a9e65961SEric Fiselier
504a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
50554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
506a9e65961SEric Fiselier    {
507a9e65961SEric Fiselier        this->__construct_from(__opt);
508a9e65961SEric Fiselier    }
509a9e65961SEric Fiselier
510a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
511f2d571c8SCasey Carter    __optional_copy_base(__optional_copy_base&&) = default;
512f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
513f2d571c8SCasey Carter    __optional_copy_base& operator=(const __optional_copy_base&) = default;
514f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
515f2d571c8SCasey Carter    __optional_copy_base& operator=(__optional_copy_base&&) = default;
516f2d571c8SCasey Carter};
517f2d571c8SCasey Carter
518f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
519f2d571c8SCasey Carterstruct __optional_move_base : __optional_copy_base<_Tp>
520f2d571c8SCasey Carter{
521f2d571c8SCasey Carter    using __optional_copy_base<_Tp>::__optional_copy_base;
522f2d571c8SCasey Carter};
523f2d571c8SCasey Carter
524f2d571c8SCasey Cartertemplate <class _Tp>
525f2d571c8SCasey Carterstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
526f2d571c8SCasey Carter{
527f2d571c8SCasey Carter    using value_type = _Tp;
528f2d571c8SCasey Carter    using __optional_copy_base<_Tp>::__optional_copy_base;
529f2d571c8SCasey Carter
530f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
531f2d571c8SCasey Carter    __optional_move_base() = default;
532f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
533f2d571c8SCasey Carter    __optional_move_base(const __optional_move_base&) = default;
534f2d571c8SCasey Carter
535f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
53654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
537a9e65961SEric Fiselier        noexcept(is_nothrow_move_constructible_v<value_type>)
538a9e65961SEric Fiselier    {
539a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__opt));
540a9e65961SEric Fiselier    }
541a9e65961SEric Fiselier
542a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
543f2d571c8SCasey Carter    __optional_move_base& operator=(const __optional_move_base&) = default;
544f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
545f2d571c8SCasey Carter    __optional_move_base& operator=(__optional_move_base&&) = default;
546f2d571c8SCasey Carter};
547f2d571c8SCasey Carter
548f2d571c8SCasey Cartertemplate <class _Tp, bool =
549f2d571c8SCasey Carter    is_trivially_destructible<_Tp>::value &&
550f2d571c8SCasey Carter    is_trivially_copy_constructible<_Tp>::value &&
551f2d571c8SCasey Carter    is_trivially_copy_assignable<_Tp>::value>
552f2d571c8SCasey Carterstruct __optional_copy_assign_base : __optional_move_base<_Tp>
553f2d571c8SCasey Carter{
554f2d571c8SCasey Carter    using __optional_move_base<_Tp>::__optional_move_base;
555f2d571c8SCasey Carter};
556f2d571c8SCasey Carter
557f2d571c8SCasey Cartertemplate <class _Tp>
558f2d571c8SCasey Carterstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
559f2d571c8SCasey Carter{
560f2d571c8SCasey Carter    using __optional_move_base<_Tp>::__optional_move_base;
561f2d571c8SCasey Carter
562f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
563f2d571c8SCasey Carter    __optional_copy_assign_base() = default;
564f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
565f2d571c8SCasey Carter    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
566f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
567f2d571c8SCasey Carter    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
568f2d571c8SCasey Carter
569f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
57054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
571a9e65961SEric Fiselier    {
572a9e65961SEric Fiselier        this->__assign_from(__opt);
573a9e65961SEric Fiselier        return *this;
574a9e65961SEric Fiselier    }
575a9e65961SEric Fiselier
576a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
577f2d571c8SCasey Carter    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
578f2d571c8SCasey Carter};
579f2d571c8SCasey Carter
580f2d571c8SCasey Cartertemplate <class _Tp, bool =
581f2d571c8SCasey Carter    is_trivially_destructible<_Tp>::value &&
582f2d571c8SCasey Carter    is_trivially_move_constructible<_Tp>::value &&
583f2d571c8SCasey Carter    is_trivially_move_assignable<_Tp>::value>
584f2d571c8SCasey Carterstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
585f2d571c8SCasey Carter{
586f2d571c8SCasey Carter    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
587f2d571c8SCasey Carter};
588f2d571c8SCasey Carter
589f2d571c8SCasey Cartertemplate <class _Tp>
590f2d571c8SCasey Carterstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
591f2d571c8SCasey Carter{
592f2d571c8SCasey Carter    using value_type = _Tp;
593f2d571c8SCasey Carter    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
594f2d571c8SCasey Carter
595f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
596f2d571c8SCasey Carter    __optional_move_assign_base() = default;
597f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
598f2d571c8SCasey Carter    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
599f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
600f2d571c8SCasey Carter    __optional_move_assign_base(__optional_move_assign_base&&) = default;
601f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
602f2d571c8SCasey Carter    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
603f2d571c8SCasey Carter
604f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
60554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
606a9e65961SEric Fiselier        noexcept(is_nothrow_move_assignable_v<value_type> &&
607a9e65961SEric Fiselier                 is_nothrow_move_constructible_v<value_type>)
608a9e65961SEric Fiselier    {
609a9e65961SEric Fiselier        this->__assign_from(_VSTD::move(__opt));
610a9e65961SEric Fiselier        return *this;
611a9e65961SEric Fiselier    }
612a9e65961SEric Fiselier};
613a9e65961SEric Fiselier
614a9e65961SEric Fiseliertemplate <class _Tp>
615a9e65961SEric Fiselierusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
616a9e65961SEric Fiselier    is_copy_constructible<_Tp>::value,
617a9e65961SEric Fiselier    is_move_constructible<_Tp>::value
618a9e65961SEric Fiselier>;
619a9e65961SEric Fiselier
620a9e65961SEric Fiseliertemplate <class _Tp>
621a9e65961SEric Fiselierusing __optional_sfinae_assign_base_t = __sfinae_assign_base<
622a9e65961SEric Fiselier    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
623a9e65961SEric Fiselier    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
624a9e65961SEric Fiselier>;
625a9e65961SEric Fiselier
626a9e65961SEric Fiseliertemplate<class _Tp>
62717cfc57dSNikolas Klauserclass optional;
62817cfc57dSNikolas Klausertemplate <class _Tp>
62917cfc57dSNikolas Klauserstruct __is_std_optional : false_type {};
63017cfc57dSNikolas Klausertemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
63117cfc57dSNikolas Klauser
63217cfc57dSNikolas Klausertemplate <class _Tp>
633a9e65961SEric Fiselierclass optional
634f2d571c8SCasey Carter    : private __optional_move_assign_base<_Tp>
635a9e65961SEric Fiselier    , private __optional_sfinae_ctor_base_t<_Tp>
636a9e65961SEric Fiselier    , private __optional_sfinae_assign_base_t<_Tp>
637a9e65961SEric Fiselier{
638f2d571c8SCasey Carter    using __base = __optional_move_assign_base<_Tp>;
639a9e65961SEric Fiselierpublic:
640a9e65961SEric Fiselier    using value_type = _Tp;
641a9e65961SEric Fiselier
642a9e65961SEric Fiselierprivate:
643a9e65961SEric Fiselier     // Disable the reference extension using this static assert.
64436db4898SMarshall Clow    static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
645a9e65961SEric Fiselier        "instantiation of optional with in_place_t is ill-formed");
646a9e65961SEric Fiselier    static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
647a9e65961SEric Fiselier        "instantiation of optional with nullopt_t is ill-formed");
648a9e65961SEric Fiselier    static_assert(!is_reference_v<value_type>,
649a9e65961SEric Fiselier        "instantiation of optional with a reference type is ill-formed");
650a9e65961SEric Fiselier    static_assert(is_destructible_v<value_type>,
651a9e65961SEric Fiselier        "instantiation of optional with a non-destructible type is ill-formed");
65236db4898SMarshall Clow    static_assert(!is_array_v<value_type>,
65336db4898SMarshall Clow        "instantiation of optional with an array type is ill-formed");
654a9e65961SEric Fiselier
655a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from _Up
656a9e65961SEric Fiselier    struct _CheckOptionalArgsConstructor {
657a9e65961SEric Fiselier      template <class _Up>
658a9e65961SEric Fiselier      static constexpr bool __enable_implicit() {
659a9e65961SEric Fiselier          return is_constructible_v<_Tp, _Up&&> &&
660a9e65961SEric Fiselier                 is_convertible_v<_Up&&, _Tp>;
661a9e65961SEric Fiselier      }
662a9e65961SEric Fiselier
663a9e65961SEric Fiselier      template <class _Up>
664a9e65961SEric Fiselier      static constexpr bool __enable_explicit() {
665a9e65961SEric Fiselier          return is_constructible_v<_Tp, _Up&&> &&
666a9e65961SEric Fiselier                 !is_convertible_v<_Up&&, _Tp>;
667a9e65961SEric Fiselier      }
668a9e65961SEric Fiselier    };
669a9e65961SEric Fiselier    template <class _Up>
6703359a17bSEric Fiselier    using _CheckOptionalArgsCtor = _If<
6713359a17bSEric Fiselier        _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
6723359a17bSEric Fiselier        _IsNotSame<__uncvref_t<_Up>, optional>::value,
673a9e65961SEric Fiselier        _CheckOptionalArgsConstructor,
674a9e65961SEric Fiselier        __check_tuple_constructor_fail
675a9e65961SEric Fiselier    >;
676a9e65961SEric Fiselier    template <class _QualUp>
677a9e65961SEric Fiselier    struct _CheckOptionalLikeConstructor {
678a9e65961SEric Fiselier      template <class _Up, class _Opt = optional<_Up>>
6793359a17bSEric Fiselier      using __check_constructible_from_opt = _Or<
680a9e65961SEric Fiselier          is_constructible<_Tp, _Opt&>,
681a9e65961SEric Fiselier          is_constructible<_Tp, _Opt const&>,
682a9e65961SEric Fiselier          is_constructible<_Tp, _Opt&&>,
683a9e65961SEric Fiselier          is_constructible<_Tp, _Opt const&&>,
684a9e65961SEric Fiselier          is_convertible<_Opt&, _Tp>,
685a9e65961SEric Fiselier          is_convertible<_Opt const&, _Tp>,
686a9e65961SEric Fiselier          is_convertible<_Opt&&, _Tp>,
687a9e65961SEric Fiselier          is_convertible<_Opt const&&, _Tp>
688a9e65961SEric Fiselier      >;
689a9e65961SEric Fiselier      template <class _Up, class _Opt = optional<_Up>>
6903359a17bSEric Fiselier      using __check_assignable_from_opt = _Or<
691a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt&>,
692a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt const&>,
693a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt&&>,
694a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt const&&>
695a9e65961SEric Fiselier      >;
696a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
697a9e65961SEric Fiselier      static constexpr bool __enable_implicit() {
698a9e65961SEric Fiselier          return is_convertible<_QUp, _Tp>::value &&
699a9e65961SEric Fiselier              !__check_constructible_from_opt<_Up>::value;
700a9e65961SEric Fiselier      }
701a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
702a9e65961SEric Fiselier      static constexpr bool __enable_explicit() {
703a9e65961SEric Fiselier          return !is_convertible<_QUp, _Tp>::value &&
704a9e65961SEric Fiselier              !__check_constructible_from_opt<_Up>::value;
705a9e65961SEric Fiselier      }
706a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
707a9e65961SEric Fiselier      static constexpr bool __enable_assign() {
708b6f19174SArthur O'Dwyer          // Construction and assignability of _QUp to _Tp has already been
709a9e65961SEric Fiselier          // checked.
710a9e65961SEric Fiselier          return !__check_constructible_from_opt<_Up>::value &&
711a9e65961SEric Fiselier              !__check_assignable_from_opt<_Up>::value;
712a9e65961SEric Fiselier      }
713a9e65961SEric Fiselier    };
714a9e65961SEric Fiselier
715a9e65961SEric Fiselier    template <class _Up, class _QualUp>
7163359a17bSEric Fiselier    using _CheckOptionalLikeCtor = _If<
7173359a17bSEric Fiselier      _And<
7183359a17bSEric Fiselier         _IsNotSame<_Up, _Tp>,
719a9e65961SEric Fiselier          is_constructible<_Tp, _QualUp>
720a9e65961SEric Fiselier      >::value,
721a9e65961SEric Fiselier      _CheckOptionalLikeConstructor<_QualUp>,
722a9e65961SEric Fiselier      __check_tuple_constructor_fail
723a9e65961SEric Fiselier    >;
724a9e65961SEric Fiselier    template <class _Up, class _QualUp>
7253359a17bSEric Fiselier    using _CheckOptionalLikeAssign = _If<
7263359a17bSEric Fiselier      _And<
7273359a17bSEric Fiselier          _IsNotSame<_Up, _Tp>,
728a9e65961SEric Fiselier          is_constructible<_Tp, _QualUp>,
729a9e65961SEric Fiselier          is_assignable<_Tp&, _QualUp>
730a9e65961SEric Fiselier      >::value,
731a9e65961SEric Fiselier      _CheckOptionalLikeConstructor<_QualUp>,
732a9e65961SEric Fiselier      __check_tuple_constructor_fail
733a9e65961SEric Fiselier    >;
73417cfc57dSNikolas Klauser
735a9e65961SEric Fiselierpublic:
736a9e65961SEric Fiselier
737a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
738c1bcd4c1SMarshall Clow    _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
739c1bcd4c1SMarshall Clow    _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
740a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
741a9e65961SEric Fiselier
7424e0ea2cfSLouis Dionne    template <class _InPlaceT, class... _Args, class = enable_if_t<
7433359a17bSEric Fiselier          _And<
7443359a17bSEric Fiselier              _IsSame<_InPlaceT, in_place_t>,
74586af6f50SEric Fiselier              is_constructible<value_type, _Args...>
74686af6f50SEric Fiselier            >::value
74786af6f50SEric Fiselier        >
748a9e65961SEric Fiselier    >
749a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
75086af6f50SEric Fiselier    constexpr explicit optional(_InPlaceT, _Args&&... __args)
751a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
752a9e65961SEric Fiselier
7534e0ea2cfSLouis Dionne    template <class _Up, class... _Args, class = enable_if_t<
754a9e65961SEric Fiselier        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
755a9e65961SEric Fiselier    >
756a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
757a9e65961SEric Fiselier    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
758a9e65961SEric Fiselier        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
759a9e65961SEric Fiselier
7604e0ea2cfSLouis Dionne    template <class _Up = value_type, enable_if_t<
761a9e65961SEric Fiselier        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
762a9e65961SEric Fiselier    , int> = 0>
763a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
764a9e65961SEric Fiselier    constexpr optional(_Up&& __v)
765a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
766a9e65961SEric Fiselier
7674e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
768a9e65961SEric Fiselier        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
769a9e65961SEric Fiselier    , int> = 0>
770a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
771a9e65961SEric Fiselier    constexpr explicit optional(_Up&& __v)
772a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
773a9e65961SEric Fiselier
774a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from const optional<_Up>&
7754e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
776a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
777a9e65961SEric Fiselier    , int> = 0>
778a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
77954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
780a9e65961SEric Fiselier    {
781a9e65961SEric Fiselier        this->__construct_from(__v);
782a9e65961SEric Fiselier    }
7834e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
784a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
785a9e65961SEric Fiselier    , int> = 0>
786a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
78754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
788a9e65961SEric Fiselier    {
789a9e65961SEric Fiselier        this->__construct_from(__v);
790a9e65961SEric Fiselier    }
791a9e65961SEric Fiselier
792a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from optional<_Up>&&
7934e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
794a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
795a9e65961SEric Fiselier    , int> = 0>
796a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
79754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
798a9e65961SEric Fiselier    {
799a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__v));
800a9e65961SEric Fiselier    }
8014e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
802a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
803a9e65961SEric Fiselier    , int> = 0>
804a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
80554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
806a9e65961SEric Fiselier    {
807a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__v));
808a9e65961SEric Fiselier    }
809a9e65961SEric Fiselier
81017cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
81117cfc57dSNikolas Klauser  template<class _Fp, class... _Args>
81217cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
81317cfc57dSNikolas Klauser  constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
81417cfc57dSNikolas Klauser      : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
81517cfc57dSNikolas Klauser  }
81617cfc57dSNikolas Klauser#endif
81717cfc57dSNikolas Klauser
818a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
81954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
820a9e65961SEric Fiselier    {
821a9e65961SEric Fiselier        reset();
822a9e65961SEric Fiselier        return *this;
823a9e65961SEric Fiselier    }
824a9e65961SEric Fiselier
825a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
826a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
827a9e65961SEric Fiselier
828a9e65961SEric Fiselier    // LWG2756
829a9e65961SEric Fiselier    template <class _Up = value_type,
8304e0ea2cfSLouis Dionne              class = enable_if_t<
8313359a17bSEric Fiselier                      _And<
8323359a17bSEric Fiselier                          _IsNotSame<__uncvref_t<_Up>, optional>,
8333359a17bSEric Fiselier                          _Or<
834954014a0SMarshall Clow                              _IsNotSame<__uncvref_t<_Up>, value_type>,
8353359a17bSEric Fiselier                              _Not<is_scalar<value_type>>
836015fcffdSEric Fiselier                          >,
837015fcffdSEric Fiselier                          is_constructible<value_type, _Up>,
838015fcffdSEric Fiselier                          is_assignable<value_type&, _Up>
839015fcffdSEric Fiselier                      >::value>
840a9e65961SEric Fiselier             >
841a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
84254644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
843a9e65961SEric Fiselier    operator=(_Up&& __v)
844a9e65961SEric Fiselier    {
845a9e65961SEric Fiselier        if (this->has_value())
846a9e65961SEric Fiselier            this->__get() = _VSTD::forward<_Up>(__v);
847a9e65961SEric Fiselier        else
848a9e65961SEric Fiselier            this->__construct(_VSTD::forward<_Up>(__v));
849a9e65961SEric Fiselier        return *this;
850a9e65961SEric Fiselier    }
851a9e65961SEric Fiselier
852a9e65961SEric Fiselier    // LWG2756
8534e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
854a9e65961SEric Fiselier        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
855a9e65961SEric Fiselier    , int> = 0>
856a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
85754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
858a9e65961SEric Fiselier    operator=(const optional<_Up>& __v)
859a9e65961SEric Fiselier    {
860a9e65961SEric Fiselier        this->__assign_from(__v);
861a9e65961SEric Fiselier        return *this;
862a9e65961SEric Fiselier    }
863a9e65961SEric Fiselier
864a9e65961SEric Fiselier    // LWG2756
8654e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
866a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
867a9e65961SEric Fiselier    , int> = 0>
868a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
86954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
870a9e65961SEric Fiselier    operator=(optional<_Up>&& __v)
871a9e65961SEric Fiselier    {
872a9e65961SEric Fiselier        this->__assign_from(_VSTD::move(__v));
873a9e65961SEric Fiselier        return *this;
874a9e65961SEric Fiselier    }
875a9e65961SEric Fiselier
876a9e65961SEric Fiselier    template <class... _Args,
8774e0ea2cfSLouis Dionne              class = enable_if_t
878a9e65961SEric Fiselier                      <
879a9e65961SEric Fiselier                          is_constructible_v<value_type, _Args...>
880a9e65961SEric Fiselier                      >
881a9e65961SEric Fiselier             >
882a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
88354644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
884a9e65961SEric Fiselier    emplace(_Args&&... __args)
885a9e65961SEric Fiselier    {
886a9e65961SEric Fiselier        reset();
887a9e65961SEric Fiselier        this->__construct(_VSTD::forward<_Args>(__args)...);
8885c80f4f6SMarshall Clow        return this->__get();
889a9e65961SEric Fiselier    }
890a9e65961SEric Fiselier
891a9e65961SEric Fiselier    template <class _Up, class... _Args,
8924e0ea2cfSLouis Dionne              class = enable_if_t
893a9e65961SEric Fiselier                      <
894a9e65961SEric Fiselier                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
895a9e65961SEric Fiselier                      >
896a9e65961SEric Fiselier             >
897a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
89854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
899a9e65961SEric Fiselier    emplace(initializer_list<_Up> __il, _Args&&... __args)
900a9e65961SEric Fiselier    {
901a9e65961SEric Fiselier        reset();
902a9e65961SEric Fiselier        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
9035c80f4f6SMarshall Clow        return this->__get();
904a9e65961SEric Fiselier    }
905a9e65961SEric Fiselier
906a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
90754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
908a9e65961SEric Fiselier        noexcept(is_nothrow_move_constructible_v<value_type> &&
909a9e65961SEric Fiselier                 is_nothrow_swappable_v<value_type>)
910a9e65961SEric Fiselier    {
911a9e65961SEric Fiselier        if (this->has_value() == __opt.has_value())
912a9e65961SEric Fiselier        {
913a9e65961SEric Fiselier            using _VSTD::swap;
914a9e65961SEric Fiselier            if (this->has_value())
915a9e65961SEric Fiselier                swap(this->__get(), __opt.__get());
916a9e65961SEric Fiselier        }
917a9e65961SEric Fiselier        else
918a9e65961SEric Fiselier        {
919a9e65961SEric Fiselier            if (this->has_value())
920a9e65961SEric Fiselier            {
921a9e65961SEric Fiselier                __opt.__construct(_VSTD::move(this->__get()));
922a9e65961SEric Fiselier                reset();
923a9e65961SEric Fiselier            }
924a9e65961SEric Fiselier            else
925a9e65961SEric Fiselier            {
926a9e65961SEric Fiselier                this->__construct(_VSTD::move(__opt.__get()));
927a9e65961SEric Fiselier                __opt.reset();
928a9e65961SEric Fiselier            }
929a9e65961SEric Fiselier        }
930a9e65961SEric Fiselier    }
931a9e65961SEric Fiselier
932a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
933a9e65961SEric Fiselier    constexpr
934a9e65961SEric Fiselier    add_pointer_t<value_type const>
935a9e65961SEric Fiselier    operator->() const
936a9e65961SEric Fiselier    {
93796100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
938a9e65961SEric Fiselier        return _VSTD::addressof(this->__get());
939a9e65961SEric Fiselier    }
940a9e65961SEric Fiselier
941a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
942a9e65961SEric Fiselier    constexpr
943a9e65961SEric Fiselier    add_pointer_t<value_type>
944a9e65961SEric Fiselier    operator->()
945a9e65961SEric Fiselier    {
94696100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
947a9e65961SEric Fiselier        return _VSTD::addressof(this->__get());
948a9e65961SEric Fiselier    }
949a9e65961SEric Fiselier
950a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
951a9e65961SEric Fiselier    constexpr
952a9e65961SEric Fiselier    const value_type&
95300044421Szoecarver    operator*() const& noexcept
954a9e65961SEric Fiselier    {
95596100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
956a9e65961SEric Fiselier        return this->__get();
957a9e65961SEric Fiselier    }
958a9e65961SEric Fiselier
959a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
960a9e65961SEric Fiselier    constexpr
961a9e65961SEric Fiselier    value_type&
96200044421Szoecarver    operator*() & noexcept
963a9e65961SEric Fiselier    {
96496100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
965a9e65961SEric Fiselier        return this->__get();
966a9e65961SEric Fiselier    }
967a9e65961SEric Fiselier
968a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
969a9e65961SEric Fiselier    constexpr
970a9e65961SEric Fiselier    value_type&&
97100044421Szoecarver    operator*() && noexcept
972a9e65961SEric Fiselier    {
97396100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
974a9e65961SEric Fiselier        return _VSTD::move(this->__get());
975a9e65961SEric Fiselier    }
976a9e65961SEric Fiselier
977a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
978a9e65961SEric Fiselier    constexpr
979a9e65961SEric Fiselier    const value_type&&
98000044421Szoecarver    operator*() const&& noexcept
981a9e65961SEric Fiselier    {
98296100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
983a9e65961SEric Fiselier        return _VSTD::move(this->__get());
984a9e65961SEric Fiselier    }
985a9e65961SEric Fiselier
986a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
987a9e65961SEric Fiselier    constexpr explicit operator bool() const noexcept { return has_value(); }
988a9e65961SEric Fiselier
989a9e65961SEric Fiselier    using __base::has_value;
990a9e65961SEric Fiselier    using __base::__get;
991a9e65961SEric Fiselier
992a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
9938a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
994a9e65961SEric Fiselier    constexpr value_type const& value() const&
995a9e65961SEric Fiselier    {
996a9e65961SEric Fiselier        if (!this->has_value())
997a9e65961SEric Fiselier            __throw_bad_optional_access();
998a9e65961SEric Fiselier        return this->__get();
999a9e65961SEric Fiselier    }
1000a9e65961SEric Fiselier
1001a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10028a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1003a9e65961SEric Fiselier    constexpr value_type& value() &
1004a9e65961SEric Fiselier    {
1005a9e65961SEric Fiselier        if (!this->has_value())
1006a9e65961SEric Fiselier            __throw_bad_optional_access();
1007a9e65961SEric Fiselier        return this->__get();
1008a9e65961SEric Fiselier    }
1009a9e65961SEric Fiselier
1010a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10118a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1012a9e65961SEric Fiselier    constexpr value_type&& value() &&
1013a9e65961SEric Fiselier    {
1014a9e65961SEric Fiselier        if (!this->has_value())
1015a9e65961SEric Fiselier            __throw_bad_optional_access();
1016a9e65961SEric Fiselier        return _VSTD::move(this->__get());
1017a9e65961SEric Fiselier    }
1018a9e65961SEric Fiselier
1019a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10208a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1021a9e65961SEric Fiselier    constexpr value_type const&& value() const&&
1022a9e65961SEric Fiselier    {
1023a9e65961SEric Fiselier        if (!this->has_value())
1024a9e65961SEric Fiselier            __throw_bad_optional_access();
1025a9e65961SEric Fiselier        return _VSTD::move(this->__get());
1026a9e65961SEric Fiselier    }
1027a9e65961SEric Fiselier
1028a9e65961SEric Fiselier    template <class _Up>
1029a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1030a9e65961SEric Fiselier    constexpr value_type value_or(_Up&& __v) const&
1031a9e65961SEric Fiselier    {
1032a9e65961SEric Fiselier        static_assert(is_copy_constructible_v<value_type>,
1033a9e65961SEric Fiselier                      "optional<T>::value_or: T must be copy constructible");
1034a9e65961SEric Fiselier        static_assert(is_convertible_v<_Up, value_type>,
1035a9e65961SEric Fiselier                      "optional<T>::value_or: U must be convertible to T");
1036a9e65961SEric Fiselier        return this->has_value() ? this->__get() :
1037a9e65961SEric Fiselier                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1038a9e65961SEric Fiselier    }
1039a9e65961SEric Fiselier
1040a9e65961SEric Fiselier    template <class _Up>
1041a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1042dd7c68bcSCasey Carter    constexpr value_type value_or(_Up&& __v) &&
1043a9e65961SEric Fiselier    {
1044a9e65961SEric Fiselier        static_assert(is_move_constructible_v<value_type>,
1045a9e65961SEric Fiselier                      "optional<T>::value_or: T must be move constructible");
1046a9e65961SEric Fiselier        static_assert(is_convertible_v<_Up, value_type>,
1047a9e65961SEric Fiselier                      "optional<T>::value_or: U must be convertible to T");
1048a9e65961SEric Fiselier        return this->has_value() ? _VSTD::move(this->__get()) :
1049a9e65961SEric Fiselier                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1050a9e65961SEric Fiselier    }
1051a9e65961SEric Fiselier
105217cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
105317cfc57dSNikolas Klauser  template<class _Func>
1054fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
105517cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) & {
105617cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, value_type&>;
105717cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
105817cfc57dSNikolas Klauser                  "Result of f(value()) must be a specialization of std::optional");
105917cfc57dSNikolas Klauser    if (*this)
106017cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
106117cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
106217cfc57dSNikolas Klauser  }
106317cfc57dSNikolas Klauser
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) const& {
106717cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, const 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) && {
107817cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, value_type&&>;
107917cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
108017cfc57dSNikolas Klauser                  "Result of f(std::move(value())) must be a specialization of std::optional");
108117cfc57dSNikolas Klauser    if (*this)
108217cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
108317cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
108417cfc57dSNikolas Klauser  }
108517cfc57dSNikolas Klauser
108617cfc57dSNikolas Klauser  template<class _Func>
108717cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
108817cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) const&& {
108917cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, const 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>
1098fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
109917cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) & {
110017cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
110117cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
110217cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
110317cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::in_place_t");
110417cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
110517cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::nullopt_t");
110617cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
110717cfc57dSNikolas Klauser    if (*this)
110817cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
110917cfc57dSNikolas Klauser    return optional<_Up>();
111017cfc57dSNikolas Klauser  }
111117cfc57dSNikolas Klauser
111217cfc57dSNikolas Klauser  template<class _Func>
1113fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
111417cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) const& {
111517cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
111617cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
111717cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
111817cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::in_place_t");
111917cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
112017cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::nullopt_t");
112117cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
112217cfc57dSNikolas Klauser    if (*this)
112317cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
112417cfc57dSNikolas Klauser    return optional<_Up>();
112517cfc57dSNikolas Klauser  }
112617cfc57dSNikolas Klauser
112717cfc57dSNikolas Klauser  template<class _Func>
1128fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
112917cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) && {
113017cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
113117cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
113217cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
113317cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::in_place_t");
113417cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
113517cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::nullopt_t");
113617cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
113717cfc57dSNikolas Klauser    if (*this)
113817cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
113917cfc57dSNikolas Klauser    return optional<_Up>();
114017cfc57dSNikolas Klauser  }
114117cfc57dSNikolas Klauser
114217cfc57dSNikolas Klauser  template<class _Func>
1143fd4cc870SLouis Dionne  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
114417cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) const&& {
114517cfc57dSNikolas Klauser    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
114617cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
114717cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
114817cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::in_place_t");
114917cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
115017cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::nullopt_t");
115117cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
115217cfc57dSNikolas Klauser    if (*this)
115317cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
115417cfc57dSNikolas Klauser    return optional<_Up>();
115517cfc57dSNikolas Klauser  }
115617cfc57dSNikolas Klauser
115717cfc57dSNikolas Klauser  template<invocable _Func>
115817cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
115917cfc57dSNikolas Klauser  constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
116017cfc57dSNikolas Klauser    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
116117cfc57dSNikolas Klauser                  "Result of f() should be the same type as this optional");
116217cfc57dSNikolas Klauser    if (*this)
116317cfc57dSNikolas Klauser      return *this;
116417cfc57dSNikolas Klauser    return _VSTD::forward<_Func>(__f)();
116517cfc57dSNikolas Klauser  }
116617cfc57dSNikolas Klauser
116717cfc57dSNikolas Klauser  template<invocable _Func>
116817cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
116917cfc57dSNikolas Klauser  constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
117017cfc57dSNikolas Klauser    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
117117cfc57dSNikolas Klauser                  "Result of f() should be the same type as this optional");
117217cfc57dSNikolas Klauser    if (*this)
117317cfc57dSNikolas Klauser      return _VSTD::move(*this);
117417cfc57dSNikolas Klauser    return _VSTD::forward<_Func>(__f)();
117517cfc57dSNikolas Klauser  }
117617cfc57dSNikolas Klauser#endif // _LIBCPP_STD_VER > 20
117717cfc57dSNikolas Klauser
1178a9e65961SEric Fiselier    using __base::reset;
1179a9e65961SEric Fiselier};
1180a9e65961SEric Fiselier
118101666904SLouis Dionne#if _LIBCPP_STD_VER >= 17
1182a8f1a715SArthur O'Dwyertemplate<class _Tp>
1183a8f1a715SArthur O'Dwyer    optional(_Tp) -> optional<_Tp>;
1184f35b4bc3SMarshall Clow#endif
1185f35b4bc3SMarshall Clow
1186a9e65961SEric Fiselier// Comparisons between optionals
1187dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1188a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
11894e0ea2cfSLouis Dionneenable_if_t<
1190ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1191ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1192a9e65961SEric Fiselier    bool
1193a9e65961SEric Fiselier>
1194dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const optional<_Up>& __y)
1195a9e65961SEric Fiselier{
1196a9e65961SEric Fiselier    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1197a9e65961SEric Fiselier        return false;
1198a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1199a9e65961SEric Fiselier        return true;
1200a9e65961SEric Fiselier    return *__x == *__y;
1201a9e65961SEric Fiselier}
1202a9e65961SEric Fiselier
1203dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1204a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12054e0ea2cfSLouis Dionneenable_if_t<
1206ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1207ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1208a9e65961SEric Fiselier    bool
1209a9e65961SEric Fiselier>
1210dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
1211a9e65961SEric Fiselier{
1212a9e65961SEric Fiselier    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1213a9e65961SEric Fiselier        return true;
1214a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1215a9e65961SEric Fiselier        return false;
1216a9e65961SEric Fiselier    return *__x != *__y;
1217a9e65961SEric Fiselier}
1218a9e65961SEric Fiselier
1219dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1220a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12214e0ea2cfSLouis Dionneenable_if_t<
1222ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1223ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1224a9e65961SEric Fiselier    bool
1225a9e65961SEric Fiselier>
1226dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const optional<_Up>& __y)
1227a9e65961SEric Fiselier{
1228a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1229a9e65961SEric Fiselier        return false;
1230a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1231a9e65961SEric Fiselier        return true;
1232a9e65961SEric Fiselier    return *__x < *__y;
1233a9e65961SEric Fiselier}
1234a9e65961SEric Fiselier
1235dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1236a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12374e0ea2cfSLouis Dionneenable_if_t<
1238ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1239ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1240a9e65961SEric Fiselier    bool
1241a9e65961SEric Fiselier>
1242dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const optional<_Up>& __y)
1243a9e65961SEric Fiselier{
1244a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1245a9e65961SEric Fiselier        return false;
1246a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1247a9e65961SEric Fiselier        return true;
1248a9e65961SEric Fiselier    return *__x > *__y;
1249a9e65961SEric Fiselier}
1250a9e65961SEric Fiselier
1251dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1252a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12534e0ea2cfSLouis Dionneenable_if_t<
1254ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1255ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1256a9e65961SEric Fiselier    bool
1257a9e65961SEric Fiselier>
1258dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
1259a9e65961SEric Fiselier{
1260a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1261a9e65961SEric Fiselier        return true;
1262a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1263a9e65961SEric Fiselier        return false;
1264a9e65961SEric Fiselier    return *__x <= *__y;
1265a9e65961SEric Fiselier}
1266a9e65961SEric Fiselier
1267dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1268a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12694e0ea2cfSLouis Dionneenable_if_t<
1270ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1271ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1272a9e65961SEric Fiselier    bool
1273a9e65961SEric Fiselier>
1274dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
1275a9e65961SEric Fiselier{
1276a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1277a9e65961SEric Fiselier        return true;
1278a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1279a9e65961SEric Fiselier        return false;
1280a9e65961SEric Fiselier    return *__x >= *__y;
1281a9e65961SEric Fiselier}
1282a9e65961SEric Fiselier
1283a9e65961SEric Fiselier// Comparisons with nullopt
1284a9e65961SEric Fiseliertemplate <class _Tp>
1285a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1286a9e65961SEric Fiselierbool
1287a9e65961SEric Fiselieroperator==(const optional<_Tp>& __x, nullopt_t) noexcept
1288a9e65961SEric Fiselier{
1289a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1290a9e65961SEric Fiselier}
1291a9e65961SEric Fiselier
1292a9e65961SEric Fiseliertemplate <class _Tp>
1293a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1294a9e65961SEric Fiselierbool
1295a9e65961SEric Fiselieroperator==(nullopt_t, const optional<_Tp>& __x) noexcept
1296a9e65961SEric Fiselier{
1297a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1298a9e65961SEric Fiselier}
1299a9e65961SEric Fiselier
1300a9e65961SEric Fiseliertemplate <class _Tp>
1301a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1302a9e65961SEric Fiselierbool
1303a9e65961SEric Fiselieroperator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1304a9e65961SEric Fiselier{
1305a9e65961SEric Fiselier    return static_cast<bool>(__x);
1306a9e65961SEric Fiselier}
1307a9e65961SEric Fiselier
1308a9e65961SEric Fiseliertemplate <class _Tp>
1309a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1310a9e65961SEric Fiselierbool
1311a9e65961SEric Fiselieroperator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1312a9e65961SEric Fiselier{
1313a9e65961SEric Fiselier    return static_cast<bool>(__x);
1314a9e65961SEric Fiselier}
1315a9e65961SEric Fiselier
1316a9e65961SEric Fiseliertemplate <class _Tp>
1317a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1318a9e65961SEric Fiselierbool
1319a9e65961SEric Fiselieroperator<(const optional<_Tp>&, nullopt_t) noexcept
1320a9e65961SEric Fiselier{
1321a9e65961SEric Fiselier    return false;
1322a9e65961SEric Fiselier}
1323a9e65961SEric Fiselier
1324a9e65961SEric Fiseliertemplate <class _Tp>
1325a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1326a9e65961SEric Fiselierbool
1327a9e65961SEric Fiselieroperator<(nullopt_t, const optional<_Tp>& __x) noexcept
1328a9e65961SEric Fiselier{
1329a9e65961SEric Fiselier    return static_cast<bool>(__x);
1330a9e65961SEric Fiselier}
1331a9e65961SEric Fiselier
1332a9e65961SEric Fiseliertemplate <class _Tp>
1333a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1334a9e65961SEric Fiselierbool
1335a9e65961SEric Fiselieroperator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1336a9e65961SEric Fiselier{
1337a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1338a9e65961SEric Fiselier}
1339a9e65961SEric Fiselier
1340a9e65961SEric Fiseliertemplate <class _Tp>
1341a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1342a9e65961SEric Fiselierbool
1343fd838227SEric Fiselieroperator<=(nullopt_t, const optional<_Tp>&) noexcept
1344a9e65961SEric Fiselier{
1345a9e65961SEric Fiselier    return true;
1346a9e65961SEric Fiselier}
1347a9e65961SEric Fiselier
1348a9e65961SEric Fiseliertemplate <class _Tp>
1349a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1350a9e65961SEric Fiselierbool
1351a9e65961SEric Fiselieroperator>(const optional<_Tp>& __x, nullopt_t) noexcept
1352a9e65961SEric Fiselier{
1353a9e65961SEric Fiselier    return static_cast<bool>(__x);
1354a9e65961SEric Fiselier}
1355a9e65961SEric Fiselier
1356a9e65961SEric Fiseliertemplate <class _Tp>
1357a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1358a9e65961SEric Fiselierbool
1359fd838227SEric Fiselieroperator>(nullopt_t, const optional<_Tp>&) noexcept
1360a9e65961SEric Fiselier{
1361a9e65961SEric Fiselier    return false;
1362a9e65961SEric Fiselier}
1363a9e65961SEric Fiselier
1364a9e65961SEric Fiseliertemplate <class _Tp>
1365a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1366a9e65961SEric Fiselierbool
1367a9e65961SEric Fiselieroperator>=(const optional<_Tp>&, nullopt_t) noexcept
1368a9e65961SEric Fiselier{
1369a9e65961SEric Fiselier    return true;
1370a9e65961SEric Fiselier}
1371a9e65961SEric Fiselier
1372a9e65961SEric Fiseliertemplate <class _Tp>
1373a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1374a9e65961SEric Fiselierbool
1375a9e65961SEric Fiselieroperator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1376a9e65961SEric Fiselier{
1377a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1378a9e65961SEric Fiselier}
1379a9e65961SEric Fiselier
1380a9e65961SEric Fiselier// Comparisons with T
1381dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1382a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
13834e0ea2cfSLouis Dionneenable_if_t<
1384ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1385ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1386a9e65961SEric Fiselier    bool
1387a9e65961SEric Fiselier>
1388dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const _Up& __v)
1389a9e65961SEric Fiselier{
1390a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x == __v : false;
1391a9e65961SEric Fiselier}
1392a9e65961SEric Fiselier
1393dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1394a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
13954e0ea2cfSLouis Dionneenable_if_t<
1396ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1397ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1398a9e65961SEric Fiselier    bool
1399a9e65961SEric Fiselier>
1400dc808af3SEric Fiselieroperator==(const _Tp& __v, const optional<_Up>& __x)
1401a9e65961SEric Fiselier{
1402a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v == *__x : false;
1403a9e65961SEric Fiselier}
1404a9e65961SEric Fiselier
1405dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1406a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14074e0ea2cfSLouis Dionneenable_if_t<
1408ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1409ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1410a9e65961SEric Fiselier    bool
1411a9e65961SEric Fiselier>
1412dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const _Up& __v)
1413a9e65961SEric Fiselier{
1414a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x != __v : true;
1415a9e65961SEric Fiselier}
1416a9e65961SEric Fiselier
1417dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1418a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14194e0ea2cfSLouis Dionneenable_if_t<
1420ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1421ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1422a9e65961SEric Fiselier    bool
1423a9e65961SEric Fiselier>
1424dc808af3SEric Fiselieroperator!=(const _Tp& __v, const optional<_Up>& __x)
1425a9e65961SEric Fiselier{
1426a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v != *__x : true;
1427a9e65961SEric Fiselier}
1428a9e65961SEric Fiselier
1429dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1430a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14314e0ea2cfSLouis Dionneenable_if_t<
1432ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1433ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1434a9e65961SEric Fiselier    bool
1435a9e65961SEric Fiselier>
1436dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const _Up& __v)
1437a9e65961SEric Fiselier{
1438a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x < __v : true;
1439a9e65961SEric Fiselier}
1440a9e65961SEric Fiselier
1441dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1442a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14434e0ea2cfSLouis Dionneenable_if_t<
1444ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1445ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1446a9e65961SEric Fiselier    bool
1447a9e65961SEric Fiselier>
1448dc808af3SEric Fiselieroperator<(const _Tp& __v, const optional<_Up>& __x)
1449a9e65961SEric Fiselier{
1450a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v < *__x : false;
1451a9e65961SEric Fiselier}
1452a9e65961SEric Fiselier
1453dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1454a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14554e0ea2cfSLouis Dionneenable_if_t<
1456ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1457ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1458a9e65961SEric Fiselier    bool
1459a9e65961SEric Fiselier>
1460dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const _Up& __v)
1461a9e65961SEric Fiselier{
1462a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x <= __v : true;
1463a9e65961SEric Fiselier}
1464a9e65961SEric Fiselier
1465dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1466a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14674e0ea2cfSLouis Dionneenable_if_t<
1468ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1469ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1470a9e65961SEric Fiselier    bool
1471a9e65961SEric Fiselier>
1472dc808af3SEric Fiselieroperator<=(const _Tp& __v, const optional<_Up>& __x)
1473a9e65961SEric Fiselier{
1474a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v <= *__x : false;
1475a9e65961SEric Fiselier}
1476a9e65961SEric Fiselier
1477dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1478a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14794e0ea2cfSLouis Dionneenable_if_t<
1480ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1481ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1482a9e65961SEric Fiselier    bool
1483a9e65961SEric Fiselier>
1484dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const _Up& __v)
1485a9e65961SEric Fiselier{
1486a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x > __v : false;
1487a9e65961SEric Fiselier}
1488a9e65961SEric Fiselier
1489dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1490a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14914e0ea2cfSLouis Dionneenable_if_t<
1492ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1493ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1494a9e65961SEric Fiselier    bool
1495a9e65961SEric Fiselier>
1496dc808af3SEric Fiselieroperator>(const _Tp& __v, const optional<_Up>& __x)
1497a9e65961SEric Fiselier{
1498a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v > *__x : true;
1499a9e65961SEric Fiselier}
1500a9e65961SEric Fiselier
1501dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1502a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
15034e0ea2cfSLouis Dionneenable_if_t<
1504ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1505ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1506a9e65961SEric Fiselier    bool
1507a9e65961SEric Fiselier>
1508dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const _Up& __v)
1509a9e65961SEric Fiselier{
1510a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x >= __v : false;
1511a9e65961SEric Fiselier}
1512a9e65961SEric Fiselier
1513dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1514a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
15154e0ea2cfSLouis Dionneenable_if_t<
1516ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1517ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1518a9e65961SEric Fiselier    bool
1519a9e65961SEric Fiselier>
1520dc808af3SEric Fiselieroperator>=(const _Tp& __v, const optional<_Up>& __x)
1521a9e65961SEric Fiselier{
1522a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v >= *__x : true;
1523a9e65961SEric Fiselier}
1524a9e65961SEric Fiselier
1525a9e65961SEric Fiselier
1526a9e65961SEric Fiseliertemplate <class _Tp>
152754644993SChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
15284e0ea2cfSLouis Dionneenable_if_t<
1529a9e65961SEric Fiselier    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1530a9e65961SEric Fiselier    void
1531a9e65961SEric Fiselier>
1532a9e65961SEric Fiselierswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1533a9e65961SEric Fiselier{
1534a9e65961SEric Fiselier    __x.swap(__y);
1535a9e65961SEric Fiselier}
1536a9e65961SEric Fiselier
1537a9e65961SEric Fiseliertemplate <class _Tp>
1538a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1539a9e65961SEric Fiselieroptional<decay_t<_Tp>> make_optional(_Tp&& __v)
1540a9e65961SEric Fiselier{
1541a9e65961SEric Fiselier    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1542a9e65961SEric Fiselier}
1543a9e65961SEric Fiselier
1544a9e65961SEric Fiseliertemplate <class _Tp, class... _Args>
1545a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1546a9e65961SEric Fiselieroptional<_Tp> make_optional(_Args&&... __args)
1547a9e65961SEric Fiselier{
1548a9e65961SEric Fiselier    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1549a9e65961SEric Fiselier}
1550a9e65961SEric Fiselier
1551a9e65961SEric Fiseliertemplate <class _Tp, class _Up, class... _Args>
1552a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1553a9e65961SEric Fiselieroptional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
1554a9e65961SEric Fiselier{
1555a9e65961SEric Fiselier    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1556a9e65961SEric Fiselier}
1557a9e65961SEric Fiselier
1558a9e65961SEric Fiseliertemplate <class _Tp>
1559f9127593SEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash<
1560f9127593SEric Fiselier    __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1561f9127593SEric Fiselier>
1562a9e65961SEric Fiselier{
1563dc066888SArthur O'Dwyer#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1564dc066888SArthur O'Dwyer    _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1565dc066888SArthur O'Dwyer    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t        result_type;
1566dc066888SArthur O'Dwyer#endif
1567a9e65961SEric Fiselier
1568a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1569dc066888SArthur O'Dwyer    size_t operator()(const optional<_Tp>& __opt) const
1570a9e65961SEric Fiselier    {
1571f9127593SEric Fiselier        return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
1572a9e65961SEric Fiselier    }
1573a9e65961SEric Fiselier};
1574a9e65961SEric Fiselier
1575a9e65961SEric Fiselier_LIBCPP_END_NAMESPACE_STD
1576a9e65961SEric Fiselier
1577a9e65961SEric Fiselier#endif // _LIBCPP_STD_VER > 14
1578a9e65961SEric Fiselier
1579a9e65961SEric Fiselier#endif // _LIBCPP_OPTIONAL
1580