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
1612eadbc86SLouis Dionne#include <__availability>
16217cfc57dSNikolas Klauser#include <__concepts/invocable.h>
163bfbd73f8SArthur O'Dwyer#include <__config>
164a9e65961SEric Fiselier#include <__debug>
1652d0f1fa4SArthur O'Dwyer#include <compare>
166a9e65961SEric Fiselier#include <functional>
167a9e65961SEric Fiselier#include <initializer_list>
168a9e65961SEric Fiselier#include <new>
169a9e65961SEric Fiselier#include <stdexcept>
170a9e65961SEric Fiselier#include <type_traits>
171a9e65961SEric Fiselier#include <utility>
172f56972e2SMarshall Clow#include <version>
173a9e65961SEric Fiselier
174*169a66eaSNikolas Klauser// TODO: remove these headers
175*169a66eaSNikolas Klauser#include <__memory/allocator_arg_t.h>
176*169a66eaSNikolas Klauser#include <__memory/uses_allocator.h>
177*169a66eaSNikolas Klauser#include <typeinfo>
178*169a66eaSNikolas Klauser
179a9e65961SEric Fiselier#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
180a9e65961SEric Fiselier#  pragma GCC system_header
181a9e65961SEric Fiselier#endif
182a9e65961SEric Fiselier
183a9e65961SEric Fiseliernamespace std  // purposefully not using versioning namespace
184a9e65961SEric Fiselier{
185a9e65961SEric Fiselier
1868a063df1SLouis Dionneclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
187e29b1ed5SMarshall Clow    : public exception
188a9e65961SEric Fiselier{
189a9e65961SEric Fiselierpublic:
190a9e65961SEric Fiselier    // Get the key function ~bad_optional_access() into the dylib
1916a1d0785SMarshall Clow    virtual ~bad_optional_access() _NOEXCEPT;
192e29b1ed5SMarshall Clow    virtual const char* what() const _NOEXCEPT;
193a9e65961SEric Fiselier};
194a9e65961SEric Fiselier
195d2b0df35SNikolas Klauser} // namespace std
196a9e65961SEric Fiselier
197a9e65961SEric Fiselier#if _LIBCPP_STD_VER > 14
198a9e65961SEric Fiselier
199a9e65961SEric Fiselier_LIBCPP_BEGIN_NAMESPACE_STD
200a9e65961SEric Fiselier
201a9e65961SEric Fiselier_LIBCPP_NORETURN
202a9e65961SEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
2038a063df1SLouis Dionne_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
204a9e65961SEric Fiseliervoid __throw_bad_optional_access() {
205a9e65961SEric Fiselier#ifndef _LIBCPP_NO_EXCEPTIONS
206a9e65961SEric Fiselier        throw bad_optional_access();
207a9e65961SEric Fiselier#else
208a9e65961SEric Fiselier        _VSTD::abort();
209a9e65961SEric Fiselier#endif
210a9e65961SEric Fiselier}
211a9e65961SEric Fiselier
212a9e65961SEric Fiselierstruct nullopt_t
213a9e65961SEric Fiselier{
214a9e65961SEric Fiselier    struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
215a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
216a9e65961SEric Fiselier};
217a9e65961SEric Fiselier
218cb793e1aSLouis Dionneinline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
219a9e65961SEric Fiselier
22017cfc57dSNikolas Klauserstruct __optional_construct_from_invoke_tag {};
22117cfc57dSNikolas Klauser
222a9e65961SEric Fiseliertemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
223a9e65961SEric Fiselierstruct __optional_destruct_base;
224a9e65961SEric Fiselier
225a9e65961SEric Fiseliertemplate <class _Tp>
226a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, false>
227a9e65961SEric Fiselier{
228a9e65961SEric Fiselier    typedef _Tp value_type;
229a9e65961SEric Fiselier    static_assert(is_object_v<value_type>,
230a9e65961SEric Fiselier        "instantiation of optional with a non-object type is undefined behavior");
231a9e65961SEric Fiselier    union
232a9e65961SEric Fiselier    {
233a9e65961SEric Fiselier        char __null_state_;
234a9e65961SEric Fiselier        value_type __val_;
235a9e65961SEric Fiselier    };
236a9e65961SEric Fiselier    bool __engaged_;
237a9e65961SEric Fiselier
238a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
23954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
240a9e65961SEric Fiselier    {
241a9e65961SEric Fiselier        if (__engaged_)
242a9e65961SEric Fiselier            __val_.~value_type();
243a9e65961SEric Fiselier    }
244a9e65961SEric Fiselier
245a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
246a9e65961SEric Fiselier    constexpr __optional_destruct_base() noexcept
247a9e65961SEric Fiselier        :  __null_state_(),
248a9e65961SEric Fiselier           __engaged_(false) {}
249a9e65961SEric Fiselier
250a9e65961SEric Fiselier    template <class... _Args>
251a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
252a9e65961SEric Fiselier    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
253a9e65961SEric Fiselier        :  __val_(_VSTD::forward<_Args>(__args)...),
254a9e65961SEric Fiselier           __engaged_(true) {}
255a9e65961SEric Fiselier
25617cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
25717cfc57dSNikolas Klauser  template <class _Fp, class... _Args>
25817cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
25917cfc57dSNikolas Klauser  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
26017cfc57dSNikolas Klauser      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
26117cfc57dSNikolas Klauser#endif
26217cfc57dSNikolas Klauser
263a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
26454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
265a9e65961SEric Fiselier    {
266a9e65961SEric Fiselier        if (__engaged_)
267a9e65961SEric Fiselier        {
268a9e65961SEric Fiselier            __val_.~value_type();
269a9e65961SEric Fiselier            __engaged_ = false;
270a9e65961SEric Fiselier        }
271a9e65961SEric Fiselier    }
272a9e65961SEric Fiselier};
273a9e65961SEric Fiselier
274a9e65961SEric Fiseliertemplate <class _Tp>
275a9e65961SEric Fiselierstruct __optional_destruct_base<_Tp, true>
276a9e65961SEric Fiselier{
277a9e65961SEric Fiselier    typedef _Tp value_type;
278a9e65961SEric Fiselier    static_assert(is_object_v<value_type>,
279a9e65961SEric Fiselier        "instantiation of optional with a non-object type is undefined behavior");
280a9e65961SEric Fiselier    union
281a9e65961SEric Fiselier    {
282a9e65961SEric Fiselier        char __null_state_;
283a9e65961SEric Fiselier        value_type __val_;
284a9e65961SEric Fiselier    };
285a9e65961SEric Fiselier    bool __engaged_;
286a9e65961SEric Fiselier
287a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
288a9e65961SEric Fiselier    constexpr __optional_destruct_base() noexcept
289a9e65961SEric Fiselier        :  __null_state_(),
290a9e65961SEric Fiselier           __engaged_(false) {}
291a9e65961SEric Fiselier
292a9e65961SEric Fiselier    template <class... _Args>
293a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
294a9e65961SEric Fiselier    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
295a9e65961SEric Fiselier        :  __val_(_VSTD::forward<_Args>(__args)...),
296a9e65961SEric Fiselier           __engaged_(true) {}
297a9e65961SEric Fiselier
29817cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
29917cfc57dSNikolas Klauser  template <class _Fp, class... _Args>
30017cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
30117cfc57dSNikolas Klauser  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
30217cfc57dSNikolas Klauser      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
30317cfc57dSNikolas Klauser#endif
30417cfc57dSNikolas Klauser
305a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
30654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
307a9e65961SEric Fiselier    {
308a9e65961SEric Fiselier        if (__engaged_)
309a9e65961SEric Fiselier        {
310a9e65961SEric Fiselier            __engaged_ = false;
311a9e65961SEric Fiselier        }
312a9e65961SEric Fiselier    }
313a9e65961SEric Fiselier};
314a9e65961SEric Fiselier
315a9e65961SEric Fiseliertemplate <class _Tp, bool = is_reference<_Tp>::value>
316a9e65961SEric Fiselierstruct __optional_storage_base : __optional_destruct_base<_Tp>
317a9e65961SEric Fiselier{
318a9e65961SEric Fiselier    using __base = __optional_destruct_base<_Tp>;
319a9e65961SEric Fiselier    using value_type = _Tp;
320a9e65961SEric Fiselier    using __base::__base;
321a9e65961SEric Fiselier
322a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
323a9e65961SEric Fiselier    constexpr bool has_value() const noexcept
324a9e65961SEric Fiselier    {
325a9e65961SEric Fiselier        return this->__engaged_;
326a9e65961SEric Fiselier    }
327a9e65961SEric Fiselier
328a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
329a9e65961SEric Fiselier    constexpr value_type& __get() & noexcept
330a9e65961SEric Fiselier    {
331a9e65961SEric Fiselier        return this->__val_;
332a9e65961SEric Fiselier    }
333a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
334a9e65961SEric Fiselier    constexpr const value_type& __get() const& noexcept
335a9e65961SEric Fiselier    {
336a9e65961SEric Fiselier        return this->__val_;
337a9e65961SEric Fiselier    }
338a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
339a9e65961SEric Fiselier    constexpr value_type&& __get() && noexcept
340a9e65961SEric Fiselier    {
341a9e65961SEric Fiselier        return _VSTD::move(this->__val_);
342a9e65961SEric Fiselier    }
343a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
344a9e65961SEric Fiselier    constexpr const value_type&& __get() const&& noexcept
345a9e65961SEric Fiselier    {
346a9e65961SEric Fiselier        return _VSTD::move(this->__val_);
347a9e65961SEric Fiselier    }
348a9e65961SEric Fiselier
349a9e65961SEric Fiselier    template <class... _Args>
350a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
35154644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
352a9e65961SEric Fiselier    {
353a9e65961SEric Fiselier        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
35454644993SChristopher Di Bella#if _LIBCPP_STD_VER > 17
35554644993SChristopher Di Bella        _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
35654644993SChristopher Di Bella#else
357a9e65961SEric Fiselier        ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
35854644993SChristopher Di Bella#endif
359a9e65961SEric Fiselier        this->__engaged_ = true;
360a9e65961SEric Fiselier    }
361a9e65961SEric Fiselier
362a9e65961SEric Fiselier    template <class _That>
363a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
36454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
365a9e65961SEric Fiselier    {
366a9e65961SEric Fiselier        if (__opt.has_value())
367a9e65961SEric Fiselier            __construct(_VSTD::forward<_That>(__opt).__get());
368a9e65961SEric Fiselier    }
369a9e65961SEric Fiselier
370a9e65961SEric Fiselier    template <class _That>
371a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
37254644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
373a9e65961SEric Fiselier    {
374a9e65961SEric Fiselier        if (this->__engaged_ == __opt.has_value())
375a9e65961SEric Fiselier        {
376a9e65961SEric Fiselier            if (this->__engaged_)
377a9e65961SEric Fiselier                this->__val_ = _VSTD::forward<_That>(__opt).__get();
378a9e65961SEric Fiselier        }
379a9e65961SEric Fiselier        else
380a9e65961SEric Fiselier        {
381a9e65961SEric Fiselier            if (this->__engaged_)
382a9e65961SEric Fiselier                this->reset();
383a9e65961SEric Fiselier            else
384a9e65961SEric Fiselier                __construct(_VSTD::forward<_That>(__opt).__get());
385a9e65961SEric Fiselier        }
386a9e65961SEric Fiselier    }
387a9e65961SEric Fiselier};
388a9e65961SEric Fiselier
389a9e65961SEric Fiselier// optional<T&> is currently required ill-formed, however it may to be in the
390a9e65961SEric Fiselier// future. For this reason it has already been implemented to ensure we can
391a9e65961SEric Fiselier// make the change in an ABI compatible manner.
392a9e65961SEric Fiseliertemplate <class _Tp>
393a9e65961SEric Fiselierstruct __optional_storage_base<_Tp, true>
394a9e65961SEric Fiselier{
395a9e65961SEric Fiselier    using value_type = _Tp;
396a9e65961SEric Fiselier    using __raw_type = remove_reference_t<_Tp>;
397a9e65961SEric Fiselier    __raw_type* __value_;
398a9e65961SEric Fiselier
399a9e65961SEric Fiselier    template <class _Up>
400a9e65961SEric Fiselier    static constexpr bool __can_bind_reference() {
401a9e65961SEric Fiselier        using _RawUp = typename remove_reference<_Up>::type;
402a9e65961SEric Fiselier        using _UpPtr = _RawUp*;
403a9e65961SEric Fiselier        using _RawTp = typename remove_reference<_Tp>::type;
404a9e65961SEric Fiselier        using _TpPtr = _RawTp*;
405a9e65961SEric Fiselier        using _CheckLValueArg = integral_constant<bool,
406a9e65961SEric Fiselier            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
407a9e65961SEric Fiselier        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
408a9e65961SEric Fiselier        ||  is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
409a9e65961SEric Fiselier        >;
410a9e65961SEric Fiselier        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
411a9e65961SEric Fiselier            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
412a9e65961SEric Fiselier                is_convertible<_UpPtr, _TpPtr>::value);
413a9e65961SEric Fiselier    }
414a9e65961SEric Fiselier
415a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
416a9e65961SEric Fiselier    constexpr __optional_storage_base() noexcept
417a9e65961SEric Fiselier        :  __value_(nullptr) {}
418a9e65961SEric Fiselier
419a9e65961SEric Fiselier    template <class _UArg>
420a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
421a9e65961SEric Fiselier    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
422a9e65961SEric Fiselier        :  __value_(_VSTD::addressof(__uarg))
423a9e65961SEric Fiselier    {
424a9e65961SEric Fiselier      static_assert(__can_bind_reference<_UArg>(),
425a9e65961SEric Fiselier        "Attempted to construct a reference element in tuple from a "
426a9e65961SEric Fiselier        "possible temporary");
427a9e65961SEric Fiselier    }
428a9e65961SEric Fiselier
429a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
43054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
431a9e65961SEric Fiselier
432a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
433a9e65961SEric Fiselier    constexpr bool has_value() const noexcept
434a9e65961SEric Fiselier      { return __value_ != nullptr; }
435a9e65961SEric Fiselier
436a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
437a9e65961SEric Fiselier    constexpr value_type& __get() const& noexcept
438a9e65961SEric Fiselier      { return *__value_; }
439a9e65961SEric Fiselier
440a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
441a9e65961SEric Fiselier    constexpr value_type&& __get() const&& noexcept
442a9e65961SEric Fiselier      { return _VSTD::forward<value_type>(*__value_); }
443a9e65961SEric Fiselier
444a9e65961SEric Fiselier    template <class _UArg>
445a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
44654644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
447a9e65961SEric Fiselier    {
448a9e65961SEric Fiselier        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
449a9e65961SEric Fiselier        static_assert(__can_bind_reference<_UArg>(),
450a9e65961SEric Fiselier            "Attempted to construct a reference element in tuple from a "
451a9e65961SEric Fiselier            "possible temporary");
452a9e65961SEric Fiselier        __value_ = _VSTD::addressof(__val);
453a9e65961SEric Fiselier    }
454a9e65961SEric Fiselier
455a9e65961SEric Fiselier    template <class _That>
456a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
45754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
458a9e65961SEric Fiselier    {
459a9e65961SEric Fiselier        if (__opt.has_value())
460a9e65961SEric Fiselier            __construct(_VSTD::forward<_That>(__opt).__get());
461a9e65961SEric Fiselier    }
462a9e65961SEric Fiselier
463a9e65961SEric Fiselier    template <class _That>
464a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
46554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
466a9e65961SEric Fiselier    {
467a9e65961SEric Fiselier        if (has_value() == __opt.has_value())
468a9e65961SEric Fiselier        {
469a9e65961SEric Fiselier            if (has_value())
470a9e65961SEric Fiselier                *__value_ = _VSTD::forward<_That>(__opt).__get();
471a9e65961SEric Fiselier        }
472a9e65961SEric Fiselier        else
473a9e65961SEric Fiselier        {
474a9e65961SEric Fiselier            if (has_value())
475a9e65961SEric Fiselier                reset();
476a9e65961SEric Fiselier            else
477a9e65961SEric Fiselier                __construct(_VSTD::forward<_That>(__opt).__get());
478a9e65961SEric Fiselier        }
479a9e65961SEric Fiselier    }
480a9e65961SEric Fiselier};
481a9e65961SEric Fiselier
482f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
483f2d571c8SCasey Carterstruct __optional_copy_base : __optional_storage_base<_Tp>
484a9e65961SEric Fiselier{
485a9e65961SEric Fiselier    using __optional_storage_base<_Tp>::__optional_storage_base;
486a9e65961SEric Fiselier};
487a9e65961SEric Fiselier
488a9e65961SEric Fiseliertemplate <class _Tp>
489f2d571c8SCasey Carterstruct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
490a9e65961SEric Fiselier{
491a9e65961SEric Fiselier    using __optional_storage_base<_Tp>::__optional_storage_base;
492a9e65961SEric Fiselier
493a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
494f2d571c8SCasey Carter    __optional_copy_base() = default;
495a9e65961SEric Fiselier
496a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
49754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
498a9e65961SEric Fiselier    {
499a9e65961SEric Fiselier        this->__construct_from(__opt);
500a9e65961SEric Fiselier    }
501a9e65961SEric Fiselier
502a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
503f2d571c8SCasey Carter    __optional_copy_base(__optional_copy_base&&) = default;
504f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
505f2d571c8SCasey Carter    __optional_copy_base& operator=(const __optional_copy_base&) = default;
506f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
507f2d571c8SCasey Carter    __optional_copy_base& operator=(__optional_copy_base&&) = default;
508f2d571c8SCasey Carter};
509f2d571c8SCasey Carter
510f2d571c8SCasey Cartertemplate <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
511f2d571c8SCasey Carterstruct __optional_move_base : __optional_copy_base<_Tp>
512f2d571c8SCasey Carter{
513f2d571c8SCasey Carter    using __optional_copy_base<_Tp>::__optional_copy_base;
514f2d571c8SCasey Carter};
515f2d571c8SCasey Carter
516f2d571c8SCasey Cartertemplate <class _Tp>
517f2d571c8SCasey Carterstruct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
518f2d571c8SCasey Carter{
519f2d571c8SCasey Carter    using value_type = _Tp;
520f2d571c8SCasey Carter    using __optional_copy_base<_Tp>::__optional_copy_base;
521f2d571c8SCasey Carter
522f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
523f2d571c8SCasey Carter    __optional_move_base() = default;
524f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
525f2d571c8SCasey Carter    __optional_move_base(const __optional_move_base&) = default;
526f2d571c8SCasey Carter
527f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
52854644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
529a9e65961SEric Fiselier        noexcept(is_nothrow_move_constructible_v<value_type>)
530a9e65961SEric Fiselier    {
531a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__opt));
532a9e65961SEric Fiselier    }
533a9e65961SEric Fiselier
534a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
535f2d571c8SCasey Carter    __optional_move_base& operator=(const __optional_move_base&) = default;
536f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
537f2d571c8SCasey Carter    __optional_move_base& operator=(__optional_move_base&&) = default;
538f2d571c8SCasey Carter};
539f2d571c8SCasey Carter
540f2d571c8SCasey Cartertemplate <class _Tp, bool =
541f2d571c8SCasey Carter    is_trivially_destructible<_Tp>::value &&
542f2d571c8SCasey Carter    is_trivially_copy_constructible<_Tp>::value &&
543f2d571c8SCasey Carter    is_trivially_copy_assignable<_Tp>::value>
544f2d571c8SCasey Carterstruct __optional_copy_assign_base : __optional_move_base<_Tp>
545f2d571c8SCasey Carter{
546f2d571c8SCasey Carter    using __optional_move_base<_Tp>::__optional_move_base;
547f2d571c8SCasey Carter};
548f2d571c8SCasey Carter
549f2d571c8SCasey Cartertemplate <class _Tp>
550f2d571c8SCasey Carterstruct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
551f2d571c8SCasey Carter{
552f2d571c8SCasey Carter    using __optional_move_base<_Tp>::__optional_move_base;
553f2d571c8SCasey Carter
554f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
555f2d571c8SCasey Carter    __optional_copy_assign_base() = default;
556f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
557f2d571c8SCasey Carter    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
558f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
559f2d571c8SCasey Carter    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
560f2d571c8SCasey Carter
561f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
56254644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
563a9e65961SEric Fiselier    {
564a9e65961SEric Fiselier        this->__assign_from(__opt);
565a9e65961SEric Fiselier        return *this;
566a9e65961SEric Fiselier    }
567a9e65961SEric Fiselier
568a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
569f2d571c8SCasey Carter    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
570f2d571c8SCasey Carter};
571f2d571c8SCasey Carter
572f2d571c8SCasey Cartertemplate <class _Tp, bool =
573f2d571c8SCasey Carter    is_trivially_destructible<_Tp>::value &&
574f2d571c8SCasey Carter    is_trivially_move_constructible<_Tp>::value &&
575f2d571c8SCasey Carter    is_trivially_move_assignable<_Tp>::value>
576f2d571c8SCasey Carterstruct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
577f2d571c8SCasey Carter{
578f2d571c8SCasey Carter    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
579f2d571c8SCasey Carter};
580f2d571c8SCasey Carter
581f2d571c8SCasey Cartertemplate <class _Tp>
582f2d571c8SCasey Carterstruct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
583f2d571c8SCasey Carter{
584f2d571c8SCasey Carter    using value_type = _Tp;
585f2d571c8SCasey Carter    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
586f2d571c8SCasey Carter
587f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
588f2d571c8SCasey Carter    __optional_move_assign_base() = default;
589f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
590f2d571c8SCasey Carter    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
591f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
592f2d571c8SCasey Carter    __optional_move_assign_base(__optional_move_assign_base&&) = default;
593f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
594f2d571c8SCasey Carter    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
595f2d571c8SCasey Carter
596f2d571c8SCasey Carter    _LIBCPP_INLINE_VISIBILITY
59754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
598a9e65961SEric Fiselier        noexcept(is_nothrow_move_assignable_v<value_type> &&
599a9e65961SEric Fiselier                 is_nothrow_move_constructible_v<value_type>)
600a9e65961SEric Fiselier    {
601a9e65961SEric Fiselier        this->__assign_from(_VSTD::move(__opt));
602a9e65961SEric Fiselier        return *this;
603a9e65961SEric Fiselier    }
604a9e65961SEric Fiselier};
605a9e65961SEric Fiselier
606a9e65961SEric Fiseliertemplate <class _Tp>
607a9e65961SEric Fiselierusing __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
608a9e65961SEric Fiselier    is_copy_constructible<_Tp>::value,
609a9e65961SEric Fiselier    is_move_constructible<_Tp>::value
610a9e65961SEric Fiselier>;
611a9e65961SEric Fiselier
612a9e65961SEric Fiseliertemplate <class _Tp>
613a9e65961SEric Fiselierusing __optional_sfinae_assign_base_t = __sfinae_assign_base<
614a9e65961SEric Fiselier    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
615a9e65961SEric Fiselier    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
616a9e65961SEric Fiselier>;
617a9e65961SEric Fiselier
618a9e65961SEric Fiseliertemplate<class _Tp>
61917cfc57dSNikolas Klauserclass optional;
62017cfc57dSNikolas Klausertemplate <class _Tp>
62117cfc57dSNikolas Klauserstruct __is_std_optional : false_type {};
62217cfc57dSNikolas Klausertemplate <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
62317cfc57dSNikolas Klauser
62417cfc57dSNikolas Klausertemplate <class _Tp>
625a9e65961SEric Fiselierclass optional
626f2d571c8SCasey Carter    : private __optional_move_assign_base<_Tp>
627a9e65961SEric Fiselier    , private __optional_sfinae_ctor_base_t<_Tp>
628a9e65961SEric Fiselier    , private __optional_sfinae_assign_base_t<_Tp>
629a9e65961SEric Fiselier{
630f2d571c8SCasey Carter    using __base = __optional_move_assign_base<_Tp>;
631a9e65961SEric Fiselierpublic:
632a9e65961SEric Fiselier    using value_type = _Tp;
633a9e65961SEric Fiselier
634a9e65961SEric Fiselierprivate:
635a9e65961SEric Fiselier     // Disable the reference extension using this static assert.
63636db4898SMarshall Clow    static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
637a9e65961SEric Fiselier        "instantiation of optional with in_place_t is ill-formed");
638a9e65961SEric Fiselier    static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
639a9e65961SEric Fiselier        "instantiation of optional with nullopt_t is ill-formed");
640a9e65961SEric Fiselier    static_assert(!is_reference_v<value_type>,
641a9e65961SEric Fiselier        "instantiation of optional with a reference type is ill-formed");
642a9e65961SEric Fiselier    static_assert(is_destructible_v<value_type>,
643a9e65961SEric Fiselier        "instantiation of optional with a non-destructible type is ill-formed");
64436db4898SMarshall Clow    static_assert(!is_array_v<value_type>,
64536db4898SMarshall Clow        "instantiation of optional with an array type is ill-formed");
646a9e65961SEric Fiselier
647a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from _Up
648a9e65961SEric Fiselier    struct _CheckOptionalArgsConstructor {
649a9e65961SEric Fiselier      template <class _Up>
650a9e65961SEric Fiselier      static constexpr bool __enable_implicit() {
651a9e65961SEric Fiselier          return is_constructible_v<_Tp, _Up&&> &&
652a9e65961SEric Fiselier                 is_convertible_v<_Up&&, _Tp>;
653a9e65961SEric Fiselier      }
654a9e65961SEric Fiselier
655a9e65961SEric Fiselier      template <class _Up>
656a9e65961SEric Fiselier      static constexpr bool __enable_explicit() {
657a9e65961SEric Fiselier          return is_constructible_v<_Tp, _Up&&> &&
658a9e65961SEric Fiselier                 !is_convertible_v<_Up&&, _Tp>;
659a9e65961SEric Fiselier      }
660a9e65961SEric Fiselier    };
661a9e65961SEric Fiselier    template <class _Up>
6623359a17bSEric Fiselier    using _CheckOptionalArgsCtor = _If<
6633359a17bSEric Fiselier        _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
6643359a17bSEric Fiselier        _IsNotSame<__uncvref_t<_Up>, optional>::value,
665a9e65961SEric Fiselier        _CheckOptionalArgsConstructor,
666a9e65961SEric Fiselier        __check_tuple_constructor_fail
667a9e65961SEric Fiselier    >;
668a9e65961SEric Fiselier    template <class _QualUp>
669a9e65961SEric Fiselier    struct _CheckOptionalLikeConstructor {
670a9e65961SEric Fiselier      template <class _Up, class _Opt = optional<_Up>>
6713359a17bSEric Fiselier      using __check_constructible_from_opt = _Or<
672a9e65961SEric Fiselier          is_constructible<_Tp, _Opt&>,
673a9e65961SEric Fiselier          is_constructible<_Tp, _Opt const&>,
674a9e65961SEric Fiselier          is_constructible<_Tp, _Opt&&>,
675a9e65961SEric Fiselier          is_constructible<_Tp, _Opt const&&>,
676a9e65961SEric Fiselier          is_convertible<_Opt&, _Tp>,
677a9e65961SEric Fiselier          is_convertible<_Opt const&, _Tp>,
678a9e65961SEric Fiselier          is_convertible<_Opt&&, _Tp>,
679a9e65961SEric Fiselier          is_convertible<_Opt const&&, _Tp>
680a9e65961SEric Fiselier      >;
681a9e65961SEric Fiselier      template <class _Up, class _Opt = optional<_Up>>
6823359a17bSEric Fiselier      using __check_assignable_from_opt = _Or<
683a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt&>,
684a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt const&>,
685a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt&&>,
686a9e65961SEric Fiselier          is_assignable<_Tp&, _Opt const&&>
687a9e65961SEric Fiselier      >;
688a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
689a9e65961SEric Fiselier      static constexpr bool __enable_implicit() {
690a9e65961SEric Fiselier          return is_convertible<_QUp, _Tp>::value &&
691a9e65961SEric Fiselier              !__check_constructible_from_opt<_Up>::value;
692a9e65961SEric Fiselier      }
693a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
694a9e65961SEric Fiselier      static constexpr bool __enable_explicit() {
695a9e65961SEric Fiselier          return !is_convertible<_QUp, _Tp>::value &&
696a9e65961SEric Fiselier              !__check_constructible_from_opt<_Up>::value;
697a9e65961SEric Fiselier      }
698a9e65961SEric Fiselier      template <class _Up, class _QUp = _QualUp>
699a9e65961SEric Fiselier      static constexpr bool __enable_assign() {
700b6f19174SArthur O'Dwyer          // Construction and assignability of _QUp to _Tp has already been
701a9e65961SEric Fiselier          // checked.
702a9e65961SEric Fiselier          return !__check_constructible_from_opt<_Up>::value &&
703a9e65961SEric Fiselier              !__check_assignable_from_opt<_Up>::value;
704a9e65961SEric Fiselier      }
705a9e65961SEric Fiselier    };
706a9e65961SEric Fiselier
707a9e65961SEric Fiselier    template <class _Up, class _QualUp>
7083359a17bSEric Fiselier    using _CheckOptionalLikeCtor = _If<
7093359a17bSEric Fiselier      _And<
7103359a17bSEric Fiselier         _IsNotSame<_Up, _Tp>,
711a9e65961SEric Fiselier          is_constructible<_Tp, _QualUp>
712a9e65961SEric Fiselier      >::value,
713a9e65961SEric Fiselier      _CheckOptionalLikeConstructor<_QualUp>,
714a9e65961SEric Fiselier      __check_tuple_constructor_fail
715a9e65961SEric Fiselier    >;
716a9e65961SEric Fiselier    template <class _Up, class _QualUp>
7173359a17bSEric Fiselier    using _CheckOptionalLikeAssign = _If<
7183359a17bSEric Fiselier      _And<
7193359a17bSEric Fiselier          _IsNotSame<_Up, _Tp>,
720a9e65961SEric Fiselier          is_constructible<_Tp, _QualUp>,
721a9e65961SEric Fiselier          is_assignable<_Tp&, _QualUp>
722a9e65961SEric Fiselier      >::value,
723a9e65961SEric Fiselier      _CheckOptionalLikeConstructor<_QualUp>,
724a9e65961SEric Fiselier      __check_tuple_constructor_fail
725a9e65961SEric Fiselier    >;
72617cfc57dSNikolas Klauser
727a9e65961SEric Fiselierpublic:
728a9e65961SEric Fiselier
729a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
730c1bcd4c1SMarshall Clow    _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
731c1bcd4c1SMarshall Clow    _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
732a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
733a9e65961SEric Fiselier
7344e0ea2cfSLouis Dionne    template <class _InPlaceT, class... _Args, class = enable_if_t<
7353359a17bSEric Fiselier          _And<
7363359a17bSEric Fiselier              _IsSame<_InPlaceT, in_place_t>,
73786af6f50SEric Fiselier              is_constructible<value_type, _Args...>
73886af6f50SEric Fiselier            >::value
73986af6f50SEric Fiselier        >
740a9e65961SEric Fiselier    >
741a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
74286af6f50SEric Fiselier    constexpr explicit optional(_InPlaceT, _Args&&... __args)
743a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
744a9e65961SEric Fiselier
7454e0ea2cfSLouis Dionne    template <class _Up, class... _Args, class = enable_if_t<
746a9e65961SEric Fiselier        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
747a9e65961SEric Fiselier    >
748a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
749a9e65961SEric Fiselier    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
750a9e65961SEric Fiselier        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
751a9e65961SEric Fiselier
7524e0ea2cfSLouis Dionne    template <class _Up = value_type, enable_if_t<
753a9e65961SEric Fiselier        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
754a9e65961SEric Fiselier    , int> = 0>
755a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
756a9e65961SEric Fiselier    constexpr optional(_Up&& __v)
757a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
758a9e65961SEric Fiselier
7594e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
760a9e65961SEric Fiselier        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
761a9e65961SEric Fiselier    , int> = 0>
762a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
763a9e65961SEric Fiselier    constexpr explicit optional(_Up&& __v)
764a9e65961SEric Fiselier        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
765a9e65961SEric Fiselier
766a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from const optional<_Up>&
7674e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
768a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
769a9e65961SEric Fiselier    , int> = 0>
770a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
77154644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
772a9e65961SEric Fiselier    {
773a9e65961SEric Fiselier        this->__construct_from(__v);
774a9e65961SEric Fiselier    }
7754e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
776a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
777a9e65961SEric Fiselier    , int> = 0>
778a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
77954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
780a9e65961SEric Fiselier    {
781a9e65961SEric Fiselier        this->__construct_from(__v);
782a9e65961SEric Fiselier    }
783a9e65961SEric Fiselier
784a9e65961SEric Fiselier    // LWG2756: conditionally explicit conversion from optional<_Up>&&
7854e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
786a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
787a9e65961SEric Fiselier    , int> = 0>
788a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
78954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
790a9e65961SEric Fiselier    {
791a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__v));
792a9e65961SEric Fiselier    }
7934e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
794a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
795a9e65961SEric Fiselier    , int> = 0>
796a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
79754644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
798a9e65961SEric Fiselier    {
799a9e65961SEric Fiselier        this->__construct_from(_VSTD::move(__v));
800a9e65961SEric Fiselier    }
801a9e65961SEric Fiselier
80217cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
80317cfc57dSNikolas Klauser  template<class _Fp, class... _Args>
80417cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
80517cfc57dSNikolas Klauser  constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
80617cfc57dSNikolas Klauser      : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
80717cfc57dSNikolas Klauser  }
80817cfc57dSNikolas Klauser#endif
80917cfc57dSNikolas Klauser
810a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
81154644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
812a9e65961SEric Fiselier    {
813a9e65961SEric Fiselier        reset();
814a9e65961SEric Fiselier        return *this;
815a9e65961SEric Fiselier    }
816a9e65961SEric Fiselier
817a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
818a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
819a9e65961SEric Fiselier
820a9e65961SEric Fiselier    // LWG2756
821a9e65961SEric Fiselier    template <class _Up = value_type,
8224e0ea2cfSLouis Dionne              class = enable_if_t<
8233359a17bSEric Fiselier                      _And<
8243359a17bSEric Fiselier                          _IsNotSame<__uncvref_t<_Up>, optional>,
8253359a17bSEric Fiselier                          _Or<
826954014a0SMarshall Clow                              _IsNotSame<__uncvref_t<_Up>, value_type>,
8273359a17bSEric Fiselier                              _Not<is_scalar<value_type>>
828015fcffdSEric Fiselier                          >,
829015fcffdSEric Fiselier                          is_constructible<value_type, _Up>,
830015fcffdSEric Fiselier                          is_assignable<value_type&, _Up>
831015fcffdSEric Fiselier                      >::value>
832a9e65961SEric Fiselier             >
833a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
83454644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
835a9e65961SEric Fiselier    operator=(_Up&& __v)
836a9e65961SEric Fiselier    {
837a9e65961SEric Fiselier        if (this->has_value())
838a9e65961SEric Fiselier            this->__get() = _VSTD::forward<_Up>(__v);
839a9e65961SEric Fiselier        else
840a9e65961SEric Fiselier            this->__construct(_VSTD::forward<_Up>(__v));
841a9e65961SEric Fiselier        return *this;
842a9e65961SEric Fiselier    }
843a9e65961SEric Fiselier
844a9e65961SEric Fiselier    // LWG2756
8454e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
846a9e65961SEric Fiselier        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
847a9e65961SEric Fiselier    , int> = 0>
848a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
84954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
850a9e65961SEric Fiselier    operator=(const optional<_Up>& __v)
851a9e65961SEric Fiselier    {
852a9e65961SEric Fiselier        this->__assign_from(__v);
853a9e65961SEric Fiselier        return *this;
854a9e65961SEric Fiselier    }
855a9e65961SEric Fiselier
856a9e65961SEric Fiselier    // LWG2756
8574e0ea2cfSLouis Dionne    template <class _Up, enable_if_t<
858a9e65961SEric Fiselier        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
859a9e65961SEric Fiselier    , int> = 0>
860a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
86154644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
862a9e65961SEric Fiselier    operator=(optional<_Up>&& __v)
863a9e65961SEric Fiselier    {
864a9e65961SEric Fiselier        this->__assign_from(_VSTD::move(__v));
865a9e65961SEric Fiselier        return *this;
866a9e65961SEric Fiselier    }
867a9e65961SEric Fiselier
868a9e65961SEric Fiselier    template <class... _Args,
8694e0ea2cfSLouis Dionne              class = enable_if_t
870a9e65961SEric Fiselier                      <
871a9e65961SEric Fiselier                          is_constructible_v<value_type, _Args...>
872a9e65961SEric Fiselier                      >
873a9e65961SEric Fiselier             >
874a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
87554644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
876a9e65961SEric Fiselier    emplace(_Args&&... __args)
877a9e65961SEric Fiselier    {
878a9e65961SEric Fiselier        reset();
879a9e65961SEric Fiselier        this->__construct(_VSTD::forward<_Args>(__args)...);
8805c80f4f6SMarshall Clow        return this->__get();
881a9e65961SEric Fiselier    }
882a9e65961SEric Fiselier
883a9e65961SEric Fiselier    template <class _Up, class... _Args,
8844e0ea2cfSLouis Dionne              class = enable_if_t
885a9e65961SEric Fiselier                      <
886a9e65961SEric Fiselier                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
887a9e65961SEric Fiselier                      >
888a9e65961SEric Fiselier             >
889a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
89054644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
891a9e65961SEric Fiselier    emplace(initializer_list<_Up> __il, _Args&&... __args)
892a9e65961SEric Fiselier    {
893a9e65961SEric Fiselier        reset();
894a9e65961SEric Fiselier        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
8955c80f4f6SMarshall Clow        return this->__get();
896a9e65961SEric Fiselier    }
897a9e65961SEric Fiselier
898a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
89954644993SChristopher Di Bella    _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
900a9e65961SEric Fiselier        noexcept(is_nothrow_move_constructible_v<value_type> &&
901a9e65961SEric Fiselier                 is_nothrow_swappable_v<value_type>)
902a9e65961SEric Fiselier    {
903a9e65961SEric Fiselier        if (this->has_value() == __opt.has_value())
904a9e65961SEric Fiselier        {
905a9e65961SEric Fiselier            using _VSTD::swap;
906a9e65961SEric Fiselier            if (this->has_value())
907a9e65961SEric Fiselier                swap(this->__get(), __opt.__get());
908a9e65961SEric Fiselier        }
909a9e65961SEric Fiselier        else
910a9e65961SEric Fiselier        {
911a9e65961SEric Fiselier            if (this->has_value())
912a9e65961SEric Fiselier            {
913a9e65961SEric Fiselier                __opt.__construct(_VSTD::move(this->__get()));
914a9e65961SEric Fiselier                reset();
915a9e65961SEric Fiselier            }
916a9e65961SEric Fiselier            else
917a9e65961SEric Fiselier            {
918a9e65961SEric Fiselier                this->__construct(_VSTD::move(__opt.__get()));
919a9e65961SEric Fiselier                __opt.reset();
920a9e65961SEric Fiselier            }
921a9e65961SEric Fiselier        }
922a9e65961SEric Fiselier    }
923a9e65961SEric Fiselier
924a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
925a9e65961SEric Fiselier    constexpr
926a9e65961SEric Fiselier    add_pointer_t<value_type const>
927a9e65961SEric Fiselier    operator->() const
928a9e65961SEric Fiselier    {
92996100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
930a9e65961SEric Fiselier        return _VSTD::addressof(this->__get());
931a9e65961SEric Fiselier    }
932a9e65961SEric Fiselier
933a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
934a9e65961SEric Fiselier    constexpr
935a9e65961SEric Fiselier    add_pointer_t<value_type>
936a9e65961SEric Fiselier    operator->()
937a9e65961SEric Fiselier    {
93896100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
939a9e65961SEric Fiselier        return _VSTD::addressof(this->__get());
940a9e65961SEric Fiselier    }
941a9e65961SEric Fiselier
942a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
943a9e65961SEric Fiselier    constexpr
944a9e65961SEric Fiselier    const value_type&
94500044421Szoecarver    operator*() const& noexcept
946a9e65961SEric Fiselier    {
94796100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
948a9e65961SEric Fiselier        return this->__get();
949a9e65961SEric Fiselier    }
950a9e65961SEric Fiselier
951a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
952a9e65961SEric Fiselier    constexpr
953a9e65961SEric Fiselier    value_type&
95400044421Szoecarver    operator*() & noexcept
955a9e65961SEric Fiselier    {
95696100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
957a9e65961SEric Fiselier        return this->__get();
958a9e65961SEric Fiselier    }
959a9e65961SEric Fiselier
960a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
961a9e65961SEric Fiselier    constexpr
962a9e65961SEric Fiselier    value_type&&
96300044421Szoecarver    operator*() && noexcept
964a9e65961SEric Fiselier    {
96596100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
966a9e65961SEric Fiselier        return _VSTD::move(this->__get());
967a9e65961SEric Fiselier    }
968a9e65961SEric Fiselier
969a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
970a9e65961SEric Fiselier    constexpr
971a9e65961SEric Fiselier    const value_type&&
97200044421Szoecarver    operator*() const&& noexcept
973a9e65961SEric Fiselier    {
97496100f15SKristina Bessonova        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
975a9e65961SEric Fiselier        return _VSTD::move(this->__get());
976a9e65961SEric Fiselier    }
977a9e65961SEric Fiselier
978a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
979a9e65961SEric Fiselier    constexpr explicit operator bool() const noexcept { return has_value(); }
980a9e65961SEric Fiselier
981a9e65961SEric Fiselier    using __base::has_value;
982a9e65961SEric Fiselier    using __base::__get;
983a9e65961SEric Fiselier
984a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
9858a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
986a9e65961SEric Fiselier    constexpr value_type const& value() const&
987a9e65961SEric Fiselier    {
988a9e65961SEric Fiselier        if (!this->has_value())
989a9e65961SEric Fiselier            __throw_bad_optional_access();
990a9e65961SEric Fiselier        return this->__get();
991a9e65961SEric Fiselier    }
992a9e65961SEric Fiselier
993a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
9948a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
995a9e65961SEric Fiselier    constexpr value_type& value() &
996a9e65961SEric Fiselier    {
997a9e65961SEric Fiselier        if (!this->has_value())
998a9e65961SEric Fiselier            __throw_bad_optional_access();
999a9e65961SEric Fiselier        return this->__get();
1000a9e65961SEric Fiselier    }
1001a9e65961SEric Fiselier
1002a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10038a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1004a9e65961SEric Fiselier    constexpr value_type&& value() &&
1005a9e65961SEric Fiselier    {
1006a9e65961SEric Fiselier        if (!this->has_value())
1007a9e65961SEric Fiselier            __throw_bad_optional_access();
1008a9e65961SEric Fiselier        return _VSTD::move(this->__get());
1009a9e65961SEric Fiselier    }
1010a9e65961SEric Fiselier
1011a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
10128a063df1SLouis Dionne    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1013a9e65961SEric Fiselier    constexpr value_type const&& value() const&&
1014a9e65961SEric Fiselier    {
1015a9e65961SEric Fiselier        if (!this->has_value())
1016a9e65961SEric Fiselier            __throw_bad_optional_access();
1017a9e65961SEric Fiselier        return _VSTD::move(this->__get());
1018a9e65961SEric Fiselier    }
1019a9e65961SEric Fiselier
1020a9e65961SEric Fiselier    template <class _Up>
1021a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1022a9e65961SEric Fiselier    constexpr value_type value_or(_Up&& __v) const&
1023a9e65961SEric Fiselier    {
1024a9e65961SEric Fiselier        static_assert(is_copy_constructible_v<value_type>,
1025a9e65961SEric Fiselier                      "optional<T>::value_or: T must be copy constructible");
1026a9e65961SEric Fiselier        static_assert(is_convertible_v<_Up, value_type>,
1027a9e65961SEric Fiselier                      "optional<T>::value_or: U must be convertible to T");
1028a9e65961SEric Fiselier        return this->has_value() ? this->__get() :
1029a9e65961SEric Fiselier                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1030a9e65961SEric Fiselier    }
1031a9e65961SEric Fiselier
1032a9e65961SEric Fiselier    template <class _Up>
1033a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1034dd7c68bcSCasey Carter    constexpr value_type value_or(_Up&& __v) &&
1035a9e65961SEric Fiselier    {
1036a9e65961SEric Fiselier        static_assert(is_move_constructible_v<value_type>,
1037a9e65961SEric Fiselier                      "optional<T>::value_or: T must be move constructible");
1038a9e65961SEric Fiselier        static_assert(is_convertible_v<_Up, value_type>,
1039a9e65961SEric Fiselier                      "optional<T>::value_or: U must be convertible to T");
1040a9e65961SEric Fiselier        return this->has_value() ? _VSTD::move(this->__get()) :
1041a9e65961SEric Fiselier                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1042a9e65961SEric Fiselier    }
1043a9e65961SEric Fiselier
104417cfc57dSNikolas Klauser#if _LIBCPP_STD_VER > 20
104517cfc57dSNikolas Klauser  template<class _Func>
104617cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
104717cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) & {
104817cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, value_type&>;
104917cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
105017cfc57dSNikolas Klauser                  "Result of f(value()) must be a specialization of std::optional");
105117cfc57dSNikolas Klauser    if (*this)
105217cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
105317cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
105417cfc57dSNikolas Klauser  }
105517cfc57dSNikolas Klauser
105617cfc57dSNikolas Klauser  template<class _Func>
105717cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
105817cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) const& {
105917cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, const value_type&>;
106017cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
106117cfc57dSNikolas Klauser                  "Result of f(value()) must be a specialization of std::optional");
106217cfc57dSNikolas Klauser    if (*this)
106317cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
106417cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
106517cfc57dSNikolas Klauser  }
106617cfc57dSNikolas Klauser
106717cfc57dSNikolas Klauser  template<class _Func>
106817cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
106917cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) && {
107017cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, value_type&&>;
107117cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
107217cfc57dSNikolas Klauser                  "Result of f(std::move(value())) must be a specialization of std::optional");
107317cfc57dSNikolas Klauser    if (*this)
107417cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
107517cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
107617cfc57dSNikolas Klauser  }
107717cfc57dSNikolas Klauser
107817cfc57dSNikolas Klauser  template<class _Func>
107917cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
108017cfc57dSNikolas Klauser  constexpr auto and_then(_Func&& __f) const&& {
108117cfc57dSNikolas Klauser    using _Up = invoke_result_t<_Func, const value_type&&>;
108217cfc57dSNikolas Klauser    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
108317cfc57dSNikolas Klauser                  "Result of f(std::move(value())) must be a specialization of std::optional");
108417cfc57dSNikolas Klauser    if (*this)
108517cfc57dSNikolas Klauser      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
108617cfc57dSNikolas Klauser    return remove_cvref_t<_Up>();
108717cfc57dSNikolas Klauser  }
108817cfc57dSNikolas Klauser
108917cfc57dSNikolas Klauser  template<class _Func>
109017cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
109117cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) & {
109217cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
109317cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
109417cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
109517cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::in_place_t");
109617cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
109717cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::nullopt_t");
109817cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
109917cfc57dSNikolas Klauser    if (*this)
110017cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
110117cfc57dSNikolas Klauser    return optional<_Up>();
110217cfc57dSNikolas Klauser  }
110317cfc57dSNikolas Klauser
110417cfc57dSNikolas Klauser  template<class _Func>
110517cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
110617cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) const& {
110717cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
110817cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
110917cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
111017cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::in_place_t");
111117cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
111217cfc57dSNikolas Klauser                  "Result of f(value()) should not be std::nullopt_t");
111317cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
111417cfc57dSNikolas Klauser    if (*this)
111517cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
111617cfc57dSNikolas Klauser    return optional<_Up>();
111717cfc57dSNikolas Klauser  }
111817cfc57dSNikolas Klauser
111917cfc57dSNikolas Klauser  template<class _Func>
112017cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
112117cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) && {
112217cfc57dSNikolas Klauser    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
112317cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
112417cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
112517cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::in_place_t");
112617cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
112717cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::nullopt_t");
112817cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
112917cfc57dSNikolas Klauser    if (*this)
113017cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
113117cfc57dSNikolas Klauser    return optional<_Up>();
113217cfc57dSNikolas Klauser  }
113317cfc57dSNikolas Klauser
113417cfc57dSNikolas Klauser  template<class _Func>
113517cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
113617cfc57dSNikolas Klauser  constexpr auto transform(_Func&& __f) const&& {
113717cfc57dSNikolas Klauser    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
113817cfc57dSNikolas Klauser    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
113917cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, in_place_t>,
114017cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::in_place_t");
114117cfc57dSNikolas Klauser    static_assert(!is_same_v<_Up, nullopt_t>,
114217cfc57dSNikolas Klauser                  "Result of f(std::move(value())) should not be std::nullopt_t");
114317cfc57dSNikolas Klauser    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
114417cfc57dSNikolas Klauser    if (*this)
114517cfc57dSNikolas Klauser      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
114617cfc57dSNikolas Klauser    return optional<_Up>();
114717cfc57dSNikolas Klauser  }
114817cfc57dSNikolas Klauser
114917cfc57dSNikolas Klauser  template<invocable _Func>
115017cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
115117cfc57dSNikolas Klauser  constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
115217cfc57dSNikolas Klauser    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
115317cfc57dSNikolas Klauser                  "Result of f() should be the same type as this optional");
115417cfc57dSNikolas Klauser    if (*this)
115517cfc57dSNikolas Klauser      return *this;
115617cfc57dSNikolas Klauser    return _VSTD::forward<_Func>(__f)();
115717cfc57dSNikolas Klauser  }
115817cfc57dSNikolas Klauser
115917cfc57dSNikolas Klauser  template<invocable _Func>
116017cfc57dSNikolas Klauser  _LIBCPP_HIDE_FROM_ABI
116117cfc57dSNikolas Klauser  constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
116217cfc57dSNikolas Klauser    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
116317cfc57dSNikolas Klauser                  "Result of f() should be the same type as this optional");
116417cfc57dSNikolas Klauser    if (*this)
116517cfc57dSNikolas Klauser      return _VSTD::move(*this);
116617cfc57dSNikolas Klauser    return _VSTD::forward<_Func>(__f)();
116717cfc57dSNikolas Klauser  }
116817cfc57dSNikolas Klauser#endif // _LIBCPP_STD_VER > 20
116917cfc57dSNikolas Klauser
1170a9e65961SEric Fiselier    using __base::reset;
1171a9e65961SEric Fiselier};
1172a9e65961SEric Fiselier
117301666904SLouis Dionne#if _LIBCPP_STD_VER >= 17
1174a8f1a715SArthur O'Dwyertemplate<class _Tp>
1175a8f1a715SArthur O'Dwyer    optional(_Tp) -> optional<_Tp>;
1176f35b4bc3SMarshall Clow#endif
1177f35b4bc3SMarshall Clow
1178a9e65961SEric Fiselier// Comparisons between optionals
1179dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1180a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
11814e0ea2cfSLouis Dionneenable_if_t<
1182ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1183ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1184a9e65961SEric Fiselier    bool
1185a9e65961SEric Fiselier>
1186dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const optional<_Up>& __y)
1187a9e65961SEric Fiselier{
1188a9e65961SEric Fiselier    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1189a9e65961SEric Fiselier        return false;
1190a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1191a9e65961SEric Fiselier        return true;
1192a9e65961SEric Fiselier    return *__x == *__y;
1193a9e65961SEric Fiselier}
1194a9e65961SEric Fiselier
1195dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1196a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
11974e0ea2cfSLouis Dionneenable_if_t<
1198ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1199ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1200a9e65961SEric Fiselier    bool
1201a9e65961SEric Fiselier>
1202dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
1203a9e65961SEric Fiselier{
1204a9e65961SEric Fiselier    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1205a9e65961SEric Fiselier        return true;
1206a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1207a9e65961SEric Fiselier        return false;
1208a9e65961SEric Fiselier    return *__x != *__y;
1209a9e65961SEric Fiselier}
1210a9e65961SEric Fiselier
1211dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1212a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12134e0ea2cfSLouis Dionneenable_if_t<
1214ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1215ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1216a9e65961SEric Fiselier    bool
1217a9e65961SEric Fiselier>
1218dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const optional<_Up>& __y)
1219a9e65961SEric Fiselier{
1220a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1221a9e65961SEric Fiselier        return false;
1222a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1223a9e65961SEric Fiselier        return true;
1224a9e65961SEric Fiselier    return *__x < *__y;
1225a9e65961SEric Fiselier}
1226a9e65961SEric Fiselier
1227dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1228a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12294e0ea2cfSLouis Dionneenable_if_t<
1230ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1231ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1232a9e65961SEric Fiselier    bool
1233a9e65961SEric Fiselier>
1234dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const optional<_Up>& __y)
1235a9e65961SEric Fiselier{
1236a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1237a9e65961SEric Fiselier        return false;
1238a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1239a9e65961SEric Fiselier        return true;
1240a9e65961SEric Fiselier    return *__x > *__y;
1241a9e65961SEric Fiselier}
1242a9e65961SEric Fiselier
1243dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1244a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12454e0ea2cfSLouis Dionneenable_if_t<
1246ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1247ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1248a9e65961SEric Fiselier    bool
1249a9e65961SEric Fiselier>
1250dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
1251a9e65961SEric Fiselier{
1252a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1253a9e65961SEric Fiselier        return true;
1254a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1255a9e65961SEric Fiselier        return false;
1256a9e65961SEric Fiselier    return *__x <= *__y;
1257a9e65961SEric Fiselier}
1258a9e65961SEric Fiselier
1259dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1260a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
12614e0ea2cfSLouis Dionneenable_if_t<
1262ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1263ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1264a9e65961SEric Fiselier    bool
1265a9e65961SEric Fiselier>
1266dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
1267a9e65961SEric Fiselier{
1268a9e65961SEric Fiselier    if (!static_cast<bool>(__y))
1269a9e65961SEric Fiselier        return true;
1270a9e65961SEric Fiselier    if (!static_cast<bool>(__x))
1271a9e65961SEric Fiselier        return false;
1272a9e65961SEric Fiselier    return *__x >= *__y;
1273a9e65961SEric Fiselier}
1274a9e65961SEric Fiselier
1275a9e65961SEric Fiselier// Comparisons with nullopt
1276a9e65961SEric Fiseliertemplate <class _Tp>
1277a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1278a9e65961SEric Fiselierbool
1279a9e65961SEric Fiselieroperator==(const optional<_Tp>& __x, nullopt_t) noexcept
1280a9e65961SEric Fiselier{
1281a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1282a9e65961SEric Fiselier}
1283a9e65961SEric Fiselier
1284a9e65961SEric Fiseliertemplate <class _Tp>
1285a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1286a9e65961SEric Fiselierbool
1287a9e65961SEric Fiselieroperator==(nullopt_t, const optional<_Tp>& __x) 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!=(const optional<_Tp>& __x, nullopt_t) 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!=(nullopt_t, const optional<_Tp>& __x) 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<(const optional<_Tp>&, nullopt_t) noexcept
1312a9e65961SEric Fiselier{
1313a9e65961SEric Fiselier    return false;
1314a9e65961SEric Fiselier}
1315a9e65961SEric Fiselier
1316a9e65961SEric Fiseliertemplate <class _Tp>
1317a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1318a9e65961SEric Fiselierbool
1319a9e65961SEric Fiselieroperator<(nullopt_t, const optional<_Tp>& __x) noexcept
1320a9e65961SEric Fiselier{
1321a9e65961SEric Fiselier    return static_cast<bool>(__x);
1322a9e65961SEric Fiselier}
1323a9e65961SEric Fiselier
1324a9e65961SEric Fiseliertemplate <class _Tp>
1325a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1326a9e65961SEric Fiselierbool
1327a9e65961SEric Fiselieroperator<=(const optional<_Tp>& __x, nullopt_t) 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
1335fd838227SEric Fiselieroperator<=(nullopt_t, const optional<_Tp>&) noexcept
1336a9e65961SEric Fiselier{
1337a9e65961SEric Fiselier    return true;
1338a9e65961SEric Fiselier}
1339a9e65961SEric Fiselier
1340a9e65961SEric Fiseliertemplate <class _Tp>
1341a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1342a9e65961SEric Fiselierbool
1343a9e65961SEric Fiselieroperator>(const optional<_Tp>& __x, nullopt_t) noexcept
1344a9e65961SEric Fiselier{
1345a9e65961SEric Fiselier    return static_cast<bool>(__x);
1346a9e65961SEric Fiselier}
1347a9e65961SEric Fiselier
1348a9e65961SEric Fiseliertemplate <class _Tp>
1349a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1350a9e65961SEric Fiselierbool
1351fd838227SEric Fiselieroperator>(nullopt_t, const optional<_Tp>&) noexcept
1352a9e65961SEric Fiselier{
1353a9e65961SEric Fiselier    return false;
1354a9e65961SEric Fiselier}
1355a9e65961SEric Fiselier
1356a9e65961SEric Fiseliertemplate <class _Tp>
1357a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1358a9e65961SEric Fiselierbool
1359a9e65961SEric Fiselieroperator>=(const optional<_Tp>&, nullopt_t) noexcept
1360a9e65961SEric Fiselier{
1361a9e65961SEric Fiselier    return true;
1362a9e65961SEric Fiselier}
1363a9e65961SEric Fiselier
1364a9e65961SEric Fiseliertemplate <class _Tp>
1365a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1366a9e65961SEric Fiselierbool
1367a9e65961SEric Fiselieroperator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1368a9e65961SEric Fiselier{
1369a9e65961SEric Fiselier    return !static_cast<bool>(__x);
1370a9e65961SEric Fiselier}
1371a9e65961SEric Fiselier
1372a9e65961SEric Fiselier// Comparisons with T
1373dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1374a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
13754e0ea2cfSLouis Dionneenable_if_t<
1376ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1377ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1378a9e65961SEric Fiselier    bool
1379a9e65961SEric Fiselier>
1380dc808af3SEric Fiselieroperator==(const optional<_Tp>& __x, const _Up& __v)
1381a9e65961SEric Fiselier{
1382a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x == __v : false;
1383a9e65961SEric Fiselier}
1384a9e65961SEric Fiselier
1385dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1386a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
13874e0ea2cfSLouis Dionneenable_if_t<
1388ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() ==
1389ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1390a9e65961SEric Fiselier    bool
1391a9e65961SEric Fiselier>
1392dc808af3SEric Fiselieroperator==(const _Tp& __v, const optional<_Up>& __x)
1393a9e65961SEric Fiselier{
1394a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v == *__x : false;
1395a9e65961SEric Fiselier}
1396a9e65961SEric Fiselier
1397dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1398a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
13994e0ea2cfSLouis Dionneenable_if_t<
1400ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1401ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1402a9e65961SEric Fiselier    bool
1403a9e65961SEric Fiselier>
1404dc808af3SEric Fiselieroperator!=(const optional<_Tp>& __x, const _Up& __v)
1405a9e65961SEric Fiselier{
1406a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x != __v : true;
1407a9e65961SEric Fiselier}
1408a9e65961SEric Fiselier
1409dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1410a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14114e0ea2cfSLouis Dionneenable_if_t<
1412ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() !=
1413ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1414a9e65961SEric Fiselier    bool
1415a9e65961SEric Fiselier>
1416dc808af3SEric Fiselieroperator!=(const _Tp& __v, const optional<_Up>& __x)
1417a9e65961SEric Fiselier{
1418a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v != *__x : true;
1419a9e65961SEric Fiselier}
1420a9e65961SEric Fiselier
1421dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1422a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14234e0ea2cfSLouis Dionneenable_if_t<
1424ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1425ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1426a9e65961SEric Fiselier    bool
1427a9e65961SEric Fiselier>
1428dc808af3SEric Fiselieroperator<(const optional<_Tp>& __x, const _Up& __v)
1429a9e65961SEric Fiselier{
1430a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x < __v : true;
1431a9e65961SEric Fiselier}
1432a9e65961SEric Fiselier
1433dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1434a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14354e0ea2cfSLouis Dionneenable_if_t<
1436ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <
1437ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1438a9e65961SEric Fiselier    bool
1439a9e65961SEric Fiselier>
1440dc808af3SEric Fiselieroperator<(const _Tp& __v, const optional<_Up>& __x)
1441a9e65961SEric Fiselier{
1442a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v < *__x : false;
1443a9e65961SEric Fiselier}
1444a9e65961SEric Fiselier
1445dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1446a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14474e0ea2cfSLouis Dionneenable_if_t<
1448ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1449ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1450a9e65961SEric Fiselier    bool
1451a9e65961SEric Fiselier>
1452dc808af3SEric Fiselieroperator<=(const optional<_Tp>& __x, const _Up& __v)
1453a9e65961SEric Fiselier{
1454a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x <= __v : true;
1455a9e65961SEric Fiselier}
1456a9e65961SEric Fiselier
1457dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1458a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14594e0ea2cfSLouis Dionneenable_if_t<
1460ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() <=
1461ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1462a9e65961SEric Fiselier    bool
1463a9e65961SEric Fiselier>
1464dc808af3SEric Fiselieroperator<=(const _Tp& __v, const optional<_Up>& __x)
1465a9e65961SEric Fiselier{
1466a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v <= *__x : false;
1467a9e65961SEric Fiselier}
1468a9e65961SEric Fiselier
1469dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1470a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14714e0ea2cfSLouis Dionneenable_if_t<
1472ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1473ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1474a9e65961SEric Fiselier    bool
1475a9e65961SEric Fiselier>
1476dc808af3SEric Fiselieroperator>(const optional<_Tp>& __x, const _Up& __v)
1477a9e65961SEric Fiselier{
1478a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x > __v : false;
1479a9e65961SEric Fiselier}
1480a9e65961SEric Fiselier
1481dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1482a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14834e0ea2cfSLouis Dionneenable_if_t<
1484ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >
1485ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1486a9e65961SEric Fiselier    bool
1487a9e65961SEric Fiselier>
1488dc808af3SEric Fiselieroperator>(const _Tp& __v, const optional<_Up>& __x)
1489a9e65961SEric Fiselier{
1490a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v > *__x : true;
1491a9e65961SEric Fiselier}
1492a9e65961SEric Fiselier
1493dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1494a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
14954e0ea2cfSLouis Dionneenable_if_t<
1496ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1497ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1498a9e65961SEric Fiselier    bool
1499a9e65961SEric Fiselier>
1500dc808af3SEric Fiselieroperator>=(const optional<_Tp>& __x, const _Up& __v)
1501a9e65961SEric Fiselier{
1502a9e65961SEric Fiselier    return static_cast<bool>(__x) ? *__x >= __v : false;
1503a9e65961SEric Fiselier}
1504a9e65961SEric Fiselier
1505dc808af3SEric Fiseliertemplate <class _Tp, class _Up>
1506a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
15074e0ea2cfSLouis Dionneenable_if_t<
1508ab3fcc50SArthur O'Dwyer    is_convertible_v<decltype(declval<const _Tp&>() >=
1509ab3fcc50SArthur O'Dwyer        declval<const _Up&>()), bool>,
1510a9e65961SEric Fiselier    bool
1511a9e65961SEric Fiselier>
1512dc808af3SEric Fiselieroperator>=(const _Tp& __v, const optional<_Up>& __x)
1513a9e65961SEric Fiselier{
1514a9e65961SEric Fiselier    return static_cast<bool>(__x) ? __v >= *__x : true;
1515a9e65961SEric Fiselier}
1516a9e65961SEric Fiselier
1517a9e65961SEric Fiselier
1518a9e65961SEric Fiseliertemplate <class _Tp>
151954644993SChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
15204e0ea2cfSLouis Dionneenable_if_t<
1521a9e65961SEric Fiselier    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1522a9e65961SEric Fiselier    void
1523a9e65961SEric Fiselier>
1524a9e65961SEric Fiselierswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1525a9e65961SEric Fiselier{
1526a9e65961SEric Fiselier    __x.swap(__y);
1527a9e65961SEric Fiselier}
1528a9e65961SEric Fiselier
1529a9e65961SEric Fiseliertemplate <class _Tp>
1530a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1531a9e65961SEric Fiselieroptional<decay_t<_Tp>> make_optional(_Tp&& __v)
1532a9e65961SEric Fiselier{
1533a9e65961SEric Fiselier    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1534a9e65961SEric Fiselier}
1535a9e65961SEric Fiselier
1536a9e65961SEric Fiseliertemplate <class _Tp, class... _Args>
1537a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1538a9e65961SEric Fiselieroptional<_Tp> make_optional(_Args&&... __args)
1539a9e65961SEric Fiselier{
1540a9e65961SEric Fiselier    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1541a9e65961SEric Fiselier}
1542a9e65961SEric Fiselier
1543a9e65961SEric Fiseliertemplate <class _Tp, class _Up, class... _Args>
1544a9e65961SEric Fiselier_LIBCPP_INLINE_VISIBILITY constexpr
1545a9e65961SEric Fiselieroptional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
1546a9e65961SEric Fiselier{
1547a9e65961SEric Fiselier    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1548a9e65961SEric Fiselier}
1549a9e65961SEric Fiselier
1550a9e65961SEric Fiseliertemplate <class _Tp>
1551f9127593SEric Fiselierstruct _LIBCPP_TEMPLATE_VIS hash<
1552f9127593SEric Fiselier    __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1553f9127593SEric Fiselier>
1554a9e65961SEric Fiselier{
1555dc066888SArthur O'Dwyer#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1556dc066888SArthur O'Dwyer    _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1557dc066888SArthur O'Dwyer    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t        result_type;
1558dc066888SArthur O'Dwyer#endif
1559a9e65961SEric Fiselier
1560a9e65961SEric Fiselier    _LIBCPP_INLINE_VISIBILITY
1561dc066888SArthur O'Dwyer    size_t operator()(const optional<_Tp>& __opt) const
1562a9e65961SEric Fiselier    {
1563f9127593SEric Fiselier        return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
1564a9e65961SEric Fiselier    }
1565a9e65961SEric Fiselier};
1566a9e65961SEric Fiselier
1567a9e65961SEric Fiselier_LIBCPP_END_NAMESPACE_STD
1568a9e65961SEric Fiselier
1569a9e65961SEric Fiselier#endif // _LIBCPP_STD_VER > 14
1570a9e65961SEric Fiselier
1571a9e65961SEric Fiselier#endif // _LIBCPP_OPTIONAL
1572