xref: /freebsd/contrib/llvm-project/libcxx/include/optional (revision 18054d0220cfc8df9c9568c437bd6fbb59d53c3c)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_OPTIONAL
11#define _LIBCPP_OPTIONAL
12
13/*
14    optional synopsis
15
16// C++1z
17
18namespace std {
19  // 23.6.3, optional for object types
20  template <class T> class optional;
21
22  // 23.6.4, no-value state indicator
23  struct nullopt_t{see below };
24  inline constexpr nullopt_t nullopt(unspecified );
25
26  // 23.6.5, class bad_optional_access
27  class bad_optional_access;
28
29  // 23.6.6, relational operators
30  template <class T, class U>
31  constexpr bool operator==(const optional<T>&, const optional<U>&);
32  template <class T, class U>
33  constexpr bool operator!=(const optional<T>&, const optional<U>&);
34  template <class T, class U>
35  constexpr bool operator<(const optional<T>&, const optional<U>&);
36  template <class T, class U>
37  constexpr bool operator>(const optional<T>&, const optional<U>&);
38  template <class T, class U>
39  constexpr bool operator<=(const optional<T>&, const optional<U>&);
40  template <class T, class U>
41  constexpr bool operator>=(const optional<T>&, const optional<U>&);
42
43  // 23.6.7 comparison with nullopt
44  template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
45  template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
46  template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
47  template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
48  template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
49  template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
50  template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
51  template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
52  template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
53  template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
54  template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
55  template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
56
57  // 23.6.8, comparison with T
58  template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
59  template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
60  template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
61  template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
62  template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
63  template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
64  template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
65  template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
66  template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
67  template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
68  template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
69  template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
70
71  // 23.6.9, specialized algorithms
72  template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
73  template <class T> constexpr optional<see below > make_optional(T&&);
74  template <class T, class... Args>
75    constexpr optional<T> make_optional(Args&&... args);
76  template <class T, class U, class... Args>
77    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
78
79  // 23.6.10, hash support
80  template <class T> struct hash;
81  template <class T> struct hash<optional<T>>;
82
83  template <class T> class optional {
84  public:
85    using value_type = T;
86
87    // 23.6.3.1, constructors
88    constexpr optional() noexcept;
89    constexpr optional(nullopt_t) noexcept;
90    optional(const optional &);
91    optional(optional &&) noexcept(see below);
92    template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
93    template <class U, class... Args>
94      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
95    template <class U = T>
96      constexpr EXPLICIT optional(U &&);
97    template <class U>
98      EXPLICIT optional(const optional<U> &);   // constexpr in C++20
99    template <class U>
100      EXPLICIT optional(optional<U> &&);        // constexpr in C++20
101
102    // 23.6.3.2, destructor
103    ~optional(); // constexpr in C++20
104
105    // 23.6.3.3, assignment
106    optional &operator=(nullopt_t) noexcept;                     // constexpr in C++20
107    optional &operator=(const optional &);                       // constexpr in C++20
108    optional &operator=(optional &&) noexcept(see below);        // constexpr in C++20
109    template <class U = T> optional &operator=(U &&);            // constexpr in C++20
110    template <class U> optional &operator=(const optional<U> &); // constexpr in C++20
111    template <class U> optional &operator=(optional<U> &&);      // constexpr in C++20
112    template <class... Args> T& emplace(Args &&...);             // constexpr in C++20
113    template <class U, class... Args>
114      T& emplace(initializer_list<U>, Args &&...);               // constexpr in C++20
115
116    // 23.6.3.4, swap
117    void swap(optional &) noexcept(see below ); // constexpr in C++20
118
119    // 23.6.3.5, observers
120    constexpr T const *operator->() const;
121    constexpr T *operator->();
122    constexpr T const &operator*() const &;
123    constexpr T &operator*() &;
124    constexpr T &&operator*() &&;
125    constexpr const T &&operator*() const &&;
126    constexpr explicit operator bool() const noexcept;
127    constexpr bool has_value() const noexcept;
128    constexpr T const &value() const &;
129    constexpr T &value() &;
130    constexpr T &&value() &&;
131    constexpr const T &&value() const &&;
132    template <class U> constexpr T value_or(U &&) const &;
133    template <class U> constexpr T value_or(U &&) &&;
134
135    // [optional.monadic], monadic operations
136    template<class F> constexpr auto and_then(F&& f) &;         // since C++23
137    template<class F> constexpr auto and_then(F&& f) &&;        // since C++23
138    template<class F> constexpr auto and_then(F&& f) const&;    // since C++23
139    template<class F> constexpr auto and_then(F&& f) const&&;   // since C++23
140    template<class F> constexpr auto transform(F&& f) &;        // since C++23
141    template<class F> constexpr auto transform(F&& f) &&;       // since C++23
142    template<class F> constexpr auto transform(F&& f) const&;   // since C++23
143    template<class F> constexpr auto transform(F&& f) const&&;  // since C++23
144    template<class F> constexpr optional or_else(F&& f) &&;     // since C++23
145    template<class F> constexpr optional or_else(F&& f) const&; // since C++23
146
147    // 23.6.3.6, modifiers
148    void reset() noexcept; // constexpr in C++20
149
150  private:
151    T *val; // exposition only
152  };
153
154template<class T>
155  optional(T) -> optional<T>;
156
157} // namespace std
158
159*/
160
161#include <__availability>
162#include <__concepts/invocable.h>
163#include <__config>
164#include <__debug>
165#include <__functional_base>
166#include <compare>
167#include <functional>
168#include <initializer_list>
169#include <new>
170#include <stdexcept>
171#include <type_traits>
172#include <utility>
173#include <version>
174
175#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
176#pragma GCC system_header
177#endif
178
179namespace std  // purposefully not using versioning namespace
180{
181
182class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
183    : public exception
184{
185public:
186    // Get the key function ~bad_optional_access() into the dylib
187    virtual ~bad_optional_access() _NOEXCEPT;
188    virtual const char* what() const _NOEXCEPT;
189};
190
191} // namespace std
192
193#if _LIBCPP_STD_VER > 14
194
195_LIBCPP_BEGIN_NAMESPACE_STD
196
197_LIBCPP_NORETURN
198inline _LIBCPP_INLINE_VISIBILITY
199_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
200void __throw_bad_optional_access() {
201#ifndef _LIBCPP_NO_EXCEPTIONS
202        throw bad_optional_access();
203#else
204        _VSTD::abort();
205#endif
206}
207
208struct nullopt_t
209{
210    struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
211    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
212};
213
214inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
215
216struct __optional_construct_from_invoke_tag {};
217
218template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
219struct __optional_destruct_base;
220
221template <class _Tp>
222struct __optional_destruct_base<_Tp, false>
223{
224    typedef _Tp value_type;
225    static_assert(is_object_v<value_type>,
226        "instantiation of optional with a non-object type is undefined behavior");
227    union
228    {
229        char __null_state_;
230        value_type __val_;
231    };
232    bool __engaged_;
233
234    _LIBCPP_INLINE_VISIBILITY
235    _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
236    {
237        if (__engaged_)
238            __val_.~value_type();
239    }
240
241    _LIBCPP_INLINE_VISIBILITY
242    constexpr __optional_destruct_base() noexcept
243        :  __null_state_(),
244           __engaged_(false) {}
245
246    template <class... _Args>
247    _LIBCPP_INLINE_VISIBILITY
248    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
249        :  __val_(_VSTD::forward<_Args>(__args)...),
250           __engaged_(true) {}
251
252#if _LIBCPP_STD_VER > 20
253  template <class _Fp, class... _Args>
254  _LIBCPP_HIDE_FROM_ABI
255  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
256      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
257#endif
258
259    _LIBCPP_INLINE_VISIBILITY
260    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
261    {
262        if (__engaged_)
263        {
264            __val_.~value_type();
265            __engaged_ = false;
266        }
267    }
268};
269
270template <class _Tp>
271struct __optional_destruct_base<_Tp, true>
272{
273    typedef _Tp value_type;
274    static_assert(is_object_v<value_type>,
275        "instantiation of optional with a non-object type is undefined behavior");
276    union
277    {
278        char __null_state_;
279        value_type __val_;
280    };
281    bool __engaged_;
282
283    _LIBCPP_INLINE_VISIBILITY
284    constexpr __optional_destruct_base() noexcept
285        :  __null_state_(),
286           __engaged_(false) {}
287
288    template <class... _Args>
289    _LIBCPP_INLINE_VISIBILITY
290    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
291        :  __val_(_VSTD::forward<_Args>(__args)...),
292           __engaged_(true) {}
293
294#if _LIBCPP_STD_VER > 20
295  template <class _Fp, class... _Args>
296  _LIBCPP_HIDE_FROM_ABI
297  constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
298      : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
299#endif
300
301    _LIBCPP_INLINE_VISIBILITY
302    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
303    {
304        if (__engaged_)
305        {
306            __engaged_ = false;
307        }
308    }
309};
310
311template <class _Tp, bool = is_reference<_Tp>::value>
312struct __optional_storage_base : __optional_destruct_base<_Tp>
313{
314    using __base = __optional_destruct_base<_Tp>;
315    using value_type = _Tp;
316    using __base::__base;
317
318    _LIBCPP_INLINE_VISIBILITY
319    constexpr bool has_value() const noexcept
320    {
321        return this->__engaged_;
322    }
323
324    _LIBCPP_INLINE_VISIBILITY
325    constexpr value_type& __get() & noexcept
326    {
327        return this->__val_;
328    }
329    _LIBCPP_INLINE_VISIBILITY
330    constexpr const value_type& __get() const& noexcept
331    {
332        return this->__val_;
333    }
334    _LIBCPP_INLINE_VISIBILITY
335    constexpr value_type&& __get() && noexcept
336    {
337        return _VSTD::move(this->__val_);
338    }
339    _LIBCPP_INLINE_VISIBILITY
340    constexpr const value_type&& __get() const&& noexcept
341    {
342        return _VSTD::move(this->__val_);
343    }
344
345    template <class... _Args>
346    _LIBCPP_INLINE_VISIBILITY
347    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
348    {
349        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
350#if _LIBCPP_STD_VER > 17
351        _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
352#else
353        ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
354#endif
355        this->__engaged_ = true;
356    }
357
358    template <class _That>
359    _LIBCPP_INLINE_VISIBILITY
360    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
361    {
362        if (__opt.has_value())
363            __construct(_VSTD::forward<_That>(__opt).__get());
364    }
365
366    template <class _That>
367    _LIBCPP_INLINE_VISIBILITY
368    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
369    {
370        if (this->__engaged_ == __opt.has_value())
371        {
372            if (this->__engaged_)
373                this->__val_ = _VSTD::forward<_That>(__opt).__get();
374        }
375        else
376        {
377            if (this->__engaged_)
378                this->reset();
379            else
380                __construct(_VSTD::forward<_That>(__opt).__get());
381        }
382    }
383};
384
385// optional<T&> is currently required ill-formed, however it may to be in the
386// future. For this reason it has already been implemented to ensure we can
387// make the change in an ABI compatible manner.
388template <class _Tp>
389struct __optional_storage_base<_Tp, true>
390{
391    using value_type = _Tp;
392    using __raw_type = remove_reference_t<_Tp>;
393    __raw_type* __value_;
394
395    template <class _Up>
396    static constexpr bool __can_bind_reference() {
397        using _RawUp = typename remove_reference<_Up>::type;
398        using _UpPtr = _RawUp*;
399        using _RawTp = typename remove_reference<_Tp>::type;
400        using _TpPtr = _RawTp*;
401        using _CheckLValueArg = integral_constant<bool,
402            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
403        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
404        ||  is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
405        >;
406        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
407            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
408                is_convertible<_UpPtr, _TpPtr>::value);
409    }
410
411    _LIBCPP_INLINE_VISIBILITY
412    constexpr __optional_storage_base() noexcept
413        :  __value_(nullptr) {}
414
415    template <class _UArg>
416    _LIBCPP_INLINE_VISIBILITY
417    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
418        :  __value_(_VSTD::addressof(__uarg))
419    {
420      static_assert(__can_bind_reference<_UArg>(),
421        "Attempted to construct a reference element in tuple from a "
422        "possible temporary");
423    }
424
425    _LIBCPP_INLINE_VISIBILITY
426    _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
427
428    _LIBCPP_INLINE_VISIBILITY
429    constexpr bool has_value() const noexcept
430      { return __value_ != nullptr; }
431
432    _LIBCPP_INLINE_VISIBILITY
433    constexpr value_type& __get() const& noexcept
434      { return *__value_; }
435
436    _LIBCPP_INLINE_VISIBILITY
437    constexpr value_type&& __get() const&& noexcept
438      { return _VSTD::forward<value_type>(*__value_); }
439
440    template <class _UArg>
441    _LIBCPP_INLINE_VISIBILITY
442    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
443    {
444        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
445        static_assert(__can_bind_reference<_UArg>(),
446            "Attempted to construct a reference element in tuple from a "
447            "possible temporary");
448        __value_ = _VSTD::addressof(__val);
449    }
450
451    template <class _That>
452    _LIBCPP_INLINE_VISIBILITY
453    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
454    {
455        if (__opt.has_value())
456            __construct(_VSTD::forward<_That>(__opt).__get());
457    }
458
459    template <class _That>
460    _LIBCPP_INLINE_VISIBILITY
461    _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
462    {
463        if (has_value() == __opt.has_value())
464        {
465            if (has_value())
466                *__value_ = _VSTD::forward<_That>(__opt).__get();
467        }
468        else
469        {
470            if (has_value())
471                reset();
472            else
473                __construct(_VSTD::forward<_That>(__opt).__get());
474        }
475    }
476};
477
478template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
479struct __optional_copy_base : __optional_storage_base<_Tp>
480{
481    using __optional_storage_base<_Tp>::__optional_storage_base;
482};
483
484template <class _Tp>
485struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
486{
487    using __optional_storage_base<_Tp>::__optional_storage_base;
488
489    _LIBCPP_INLINE_VISIBILITY
490    __optional_copy_base() = default;
491
492    _LIBCPP_INLINE_VISIBILITY
493    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
494    {
495        this->__construct_from(__opt);
496    }
497
498    _LIBCPP_INLINE_VISIBILITY
499    __optional_copy_base(__optional_copy_base&&) = default;
500    _LIBCPP_INLINE_VISIBILITY
501    __optional_copy_base& operator=(const __optional_copy_base&) = default;
502    _LIBCPP_INLINE_VISIBILITY
503    __optional_copy_base& operator=(__optional_copy_base&&) = default;
504};
505
506template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
507struct __optional_move_base : __optional_copy_base<_Tp>
508{
509    using __optional_copy_base<_Tp>::__optional_copy_base;
510};
511
512template <class _Tp>
513struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
514{
515    using value_type = _Tp;
516    using __optional_copy_base<_Tp>::__optional_copy_base;
517
518    _LIBCPP_INLINE_VISIBILITY
519    __optional_move_base() = default;
520    _LIBCPP_INLINE_VISIBILITY
521    __optional_move_base(const __optional_move_base&) = default;
522
523    _LIBCPP_INLINE_VISIBILITY
524    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
525        noexcept(is_nothrow_move_constructible_v<value_type>)
526    {
527        this->__construct_from(_VSTD::move(__opt));
528    }
529
530    _LIBCPP_INLINE_VISIBILITY
531    __optional_move_base& operator=(const __optional_move_base&) = default;
532    _LIBCPP_INLINE_VISIBILITY
533    __optional_move_base& operator=(__optional_move_base&&) = default;
534};
535
536template <class _Tp, bool =
537    is_trivially_destructible<_Tp>::value &&
538    is_trivially_copy_constructible<_Tp>::value &&
539    is_trivially_copy_assignable<_Tp>::value>
540struct __optional_copy_assign_base : __optional_move_base<_Tp>
541{
542    using __optional_move_base<_Tp>::__optional_move_base;
543};
544
545template <class _Tp>
546struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
547{
548    using __optional_move_base<_Tp>::__optional_move_base;
549
550    _LIBCPP_INLINE_VISIBILITY
551    __optional_copy_assign_base() = default;
552    _LIBCPP_INLINE_VISIBILITY
553    __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
554    _LIBCPP_INLINE_VISIBILITY
555    __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
556
557    _LIBCPP_INLINE_VISIBILITY
558    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
559    {
560        this->__assign_from(__opt);
561        return *this;
562    }
563
564    _LIBCPP_INLINE_VISIBILITY
565    __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
566};
567
568template <class _Tp, bool =
569    is_trivially_destructible<_Tp>::value &&
570    is_trivially_move_constructible<_Tp>::value &&
571    is_trivially_move_assignable<_Tp>::value>
572struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
573{
574    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
575};
576
577template <class _Tp>
578struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
579{
580    using value_type = _Tp;
581    using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
582
583    _LIBCPP_INLINE_VISIBILITY
584    __optional_move_assign_base() = default;
585    _LIBCPP_INLINE_VISIBILITY
586    __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
587    _LIBCPP_INLINE_VISIBILITY
588    __optional_move_assign_base(__optional_move_assign_base&&) = default;
589    _LIBCPP_INLINE_VISIBILITY
590    __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
591
592    _LIBCPP_INLINE_VISIBILITY
593    _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
594        noexcept(is_nothrow_move_assignable_v<value_type> &&
595                 is_nothrow_move_constructible_v<value_type>)
596    {
597        this->__assign_from(_VSTD::move(__opt));
598        return *this;
599    }
600};
601
602template <class _Tp>
603using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
604    is_copy_constructible<_Tp>::value,
605    is_move_constructible<_Tp>::value
606>;
607
608template <class _Tp>
609using __optional_sfinae_assign_base_t = __sfinae_assign_base<
610    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
611    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
612>;
613
614template<class _Tp>
615class optional;
616template <class _Tp>
617struct __is_std_optional : false_type {};
618template <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
619
620template <class _Tp>
621class optional
622    : private __optional_move_assign_base<_Tp>
623    , private __optional_sfinae_ctor_base_t<_Tp>
624    , private __optional_sfinae_assign_base_t<_Tp>
625{
626    using __base = __optional_move_assign_base<_Tp>;
627public:
628    using value_type = _Tp;
629
630private:
631     // Disable the reference extension using this static assert.
632    static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
633        "instantiation of optional with in_place_t is ill-formed");
634    static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
635        "instantiation of optional with nullopt_t is ill-formed");
636    static_assert(!is_reference_v<value_type>,
637        "instantiation of optional with a reference type is ill-formed");
638    static_assert(is_destructible_v<value_type>,
639        "instantiation of optional with a non-destructible type is ill-formed");
640    static_assert(!is_array_v<value_type>,
641        "instantiation of optional with an array type is ill-formed");
642
643    // LWG2756: conditionally explicit conversion from _Up
644    struct _CheckOptionalArgsConstructor {
645      template <class _Up>
646      static constexpr bool __enable_implicit() {
647          return is_constructible_v<_Tp, _Up&&> &&
648                 is_convertible_v<_Up&&, _Tp>;
649      }
650
651      template <class _Up>
652      static constexpr bool __enable_explicit() {
653          return is_constructible_v<_Tp, _Up&&> &&
654                 !is_convertible_v<_Up&&, _Tp>;
655      }
656    };
657    template <class _Up>
658    using _CheckOptionalArgsCtor = _If<
659        _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
660        _IsNotSame<__uncvref_t<_Up>, optional>::value,
661        _CheckOptionalArgsConstructor,
662        __check_tuple_constructor_fail
663    >;
664    template <class _QualUp>
665    struct _CheckOptionalLikeConstructor {
666      template <class _Up, class _Opt = optional<_Up>>
667      using __check_constructible_from_opt = _Or<
668          is_constructible<_Tp, _Opt&>,
669          is_constructible<_Tp, _Opt const&>,
670          is_constructible<_Tp, _Opt&&>,
671          is_constructible<_Tp, _Opt const&&>,
672          is_convertible<_Opt&, _Tp>,
673          is_convertible<_Opt const&, _Tp>,
674          is_convertible<_Opt&&, _Tp>,
675          is_convertible<_Opt const&&, _Tp>
676      >;
677      template <class _Up, class _Opt = optional<_Up>>
678      using __check_assignable_from_opt = _Or<
679          is_assignable<_Tp&, _Opt&>,
680          is_assignable<_Tp&, _Opt const&>,
681          is_assignable<_Tp&, _Opt&&>,
682          is_assignable<_Tp&, _Opt const&&>
683      >;
684      template <class _Up, class _QUp = _QualUp>
685      static constexpr bool __enable_implicit() {
686          return is_convertible<_QUp, _Tp>::value &&
687              !__check_constructible_from_opt<_Up>::value;
688      }
689      template <class _Up, class _QUp = _QualUp>
690      static constexpr bool __enable_explicit() {
691          return !is_convertible<_QUp, _Tp>::value &&
692              !__check_constructible_from_opt<_Up>::value;
693      }
694      template <class _Up, class _QUp = _QualUp>
695      static constexpr bool __enable_assign() {
696          // Construction and assignability of _QUp to _Tp has already been
697          // checked.
698          return !__check_constructible_from_opt<_Up>::value &&
699              !__check_assignable_from_opt<_Up>::value;
700      }
701    };
702
703    template <class _Up, class _QualUp>
704    using _CheckOptionalLikeCtor = _If<
705      _And<
706         _IsNotSame<_Up, _Tp>,
707          is_constructible<_Tp, _QualUp>
708      >::value,
709      _CheckOptionalLikeConstructor<_QualUp>,
710      __check_tuple_constructor_fail
711    >;
712    template <class _Up, class _QualUp>
713    using _CheckOptionalLikeAssign = _If<
714      _And<
715          _IsNotSame<_Up, _Tp>,
716          is_constructible<_Tp, _QualUp>,
717          is_assignable<_Tp&, _QualUp>
718      >::value,
719      _CheckOptionalLikeConstructor<_QualUp>,
720      __check_tuple_constructor_fail
721    >;
722
723public:
724
725    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
726    _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
727    _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
728    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
729
730    template <class _InPlaceT, class... _Args, class = enable_if_t<
731          _And<
732              _IsSame<_InPlaceT, in_place_t>,
733              is_constructible<value_type, _Args...>
734            >::value
735        >
736    >
737    _LIBCPP_INLINE_VISIBILITY
738    constexpr explicit optional(_InPlaceT, _Args&&... __args)
739        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
740
741    template <class _Up, class... _Args, class = enable_if_t<
742        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
743    >
744    _LIBCPP_INLINE_VISIBILITY
745    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
746        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
747
748    template <class _Up = value_type, enable_if_t<
749        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
750    , int> = 0>
751    _LIBCPP_INLINE_VISIBILITY
752    constexpr optional(_Up&& __v)
753        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
754
755    template <class _Up, enable_if_t<
756        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
757    , int> = 0>
758    _LIBCPP_INLINE_VISIBILITY
759    constexpr explicit optional(_Up&& __v)
760        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
761
762    // LWG2756: conditionally explicit conversion from const optional<_Up>&
763    template <class _Up, enable_if_t<
764        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
765    , int> = 0>
766    _LIBCPP_INLINE_VISIBILITY
767    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
768    {
769        this->__construct_from(__v);
770    }
771    template <class _Up, enable_if_t<
772        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
773    , int> = 0>
774    _LIBCPP_INLINE_VISIBILITY
775    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
776    {
777        this->__construct_from(__v);
778    }
779
780    // LWG2756: conditionally explicit conversion from optional<_Up>&&
781    template <class _Up, enable_if_t<
782        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
783    , int> = 0>
784    _LIBCPP_INLINE_VISIBILITY
785    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
786    {
787        this->__construct_from(_VSTD::move(__v));
788    }
789    template <class _Up, enable_if_t<
790        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
791    , int> = 0>
792    _LIBCPP_INLINE_VISIBILITY
793    _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
794    {
795        this->__construct_from(_VSTD::move(__v));
796    }
797
798#if _LIBCPP_STD_VER > 20
799  template<class _Fp, class... _Args>
800  _LIBCPP_HIDE_FROM_ABI
801  constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
802      : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
803  }
804#endif
805
806    _LIBCPP_INLINE_VISIBILITY
807    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
808    {
809        reset();
810        return *this;
811    }
812
813    _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
814    _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
815
816    // LWG2756
817    template <class _Up = value_type,
818              class = enable_if_t<
819                      _And<
820                          _IsNotSame<__uncvref_t<_Up>, optional>,
821                          _Or<
822                              _IsNotSame<__uncvref_t<_Up>, value_type>,
823                              _Not<is_scalar<value_type>>
824                          >,
825                          is_constructible<value_type, _Up>,
826                          is_assignable<value_type&, _Up>
827                      >::value>
828             >
829    _LIBCPP_INLINE_VISIBILITY
830    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
831    operator=(_Up&& __v)
832    {
833        if (this->has_value())
834            this->__get() = _VSTD::forward<_Up>(__v);
835        else
836            this->__construct(_VSTD::forward<_Up>(__v));
837        return *this;
838    }
839
840    // LWG2756
841    template <class _Up, enable_if_t<
842        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
843    , int> = 0>
844    _LIBCPP_INLINE_VISIBILITY
845    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
846    operator=(const optional<_Up>& __v)
847    {
848        this->__assign_from(__v);
849        return *this;
850    }
851
852    // LWG2756
853    template <class _Up, enable_if_t<
854        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
855    , int> = 0>
856    _LIBCPP_INLINE_VISIBILITY
857    _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
858    operator=(optional<_Up>&& __v)
859    {
860        this->__assign_from(_VSTD::move(__v));
861        return *this;
862    }
863
864    template <class... _Args,
865              class = enable_if_t
866                      <
867                          is_constructible_v<value_type, _Args...>
868                      >
869             >
870    _LIBCPP_INLINE_VISIBILITY
871    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
872    emplace(_Args&&... __args)
873    {
874        reset();
875        this->__construct(_VSTD::forward<_Args>(__args)...);
876        return this->__get();
877    }
878
879    template <class _Up, class... _Args,
880              class = enable_if_t
881                      <
882                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
883                      >
884             >
885    _LIBCPP_INLINE_VISIBILITY
886    _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
887    emplace(initializer_list<_Up> __il, _Args&&... __args)
888    {
889        reset();
890        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
891        return this->__get();
892    }
893
894    _LIBCPP_INLINE_VISIBILITY
895    _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
896        noexcept(is_nothrow_move_constructible_v<value_type> &&
897                 is_nothrow_swappable_v<value_type>)
898    {
899        if (this->has_value() == __opt.has_value())
900        {
901            using _VSTD::swap;
902            if (this->has_value())
903                swap(this->__get(), __opt.__get());
904        }
905        else
906        {
907            if (this->has_value())
908            {
909                __opt.__construct(_VSTD::move(this->__get()));
910                reset();
911            }
912            else
913            {
914                this->__construct(_VSTD::move(__opt.__get()));
915                __opt.reset();
916            }
917        }
918    }
919
920    _LIBCPP_INLINE_VISIBILITY
921    constexpr
922    add_pointer_t<value_type const>
923    operator->() const
924    {
925        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
926        return _VSTD::addressof(this->__get());
927    }
928
929    _LIBCPP_INLINE_VISIBILITY
930    constexpr
931    add_pointer_t<value_type>
932    operator->()
933    {
934        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
935        return _VSTD::addressof(this->__get());
936    }
937
938    _LIBCPP_INLINE_VISIBILITY
939    constexpr
940    const value_type&
941    operator*() const& noexcept
942    {
943        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
944        return this->__get();
945    }
946
947    _LIBCPP_INLINE_VISIBILITY
948    constexpr
949    value_type&
950    operator*() & noexcept
951    {
952        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
953        return this->__get();
954    }
955
956    _LIBCPP_INLINE_VISIBILITY
957    constexpr
958    value_type&&
959    operator*() && noexcept
960    {
961        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
962        return _VSTD::move(this->__get());
963    }
964
965    _LIBCPP_INLINE_VISIBILITY
966    constexpr
967    const value_type&&
968    operator*() const&& noexcept
969    {
970        _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
971        return _VSTD::move(this->__get());
972    }
973
974    _LIBCPP_INLINE_VISIBILITY
975    constexpr explicit operator bool() const noexcept { return has_value(); }
976
977    using __base::has_value;
978    using __base::__get;
979
980    _LIBCPP_INLINE_VISIBILITY
981    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
982    constexpr value_type const& value() const&
983    {
984        if (!this->has_value())
985            __throw_bad_optional_access();
986        return this->__get();
987    }
988
989    _LIBCPP_INLINE_VISIBILITY
990    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
991    constexpr value_type& value() &
992    {
993        if (!this->has_value())
994            __throw_bad_optional_access();
995        return this->__get();
996    }
997
998    _LIBCPP_INLINE_VISIBILITY
999    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1000    constexpr value_type&& value() &&
1001    {
1002        if (!this->has_value())
1003            __throw_bad_optional_access();
1004        return _VSTD::move(this->__get());
1005    }
1006
1007    _LIBCPP_INLINE_VISIBILITY
1008    _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
1009    constexpr value_type const&& value() const&&
1010    {
1011        if (!this->has_value())
1012            __throw_bad_optional_access();
1013        return _VSTD::move(this->__get());
1014    }
1015
1016    template <class _Up>
1017    _LIBCPP_INLINE_VISIBILITY
1018    constexpr value_type value_or(_Up&& __v) const&
1019    {
1020        static_assert(is_copy_constructible_v<value_type>,
1021                      "optional<T>::value_or: T must be copy constructible");
1022        static_assert(is_convertible_v<_Up, value_type>,
1023                      "optional<T>::value_or: U must be convertible to T");
1024        return this->has_value() ? this->__get() :
1025                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1026    }
1027
1028    template <class _Up>
1029    _LIBCPP_INLINE_VISIBILITY
1030    constexpr value_type value_or(_Up&& __v) &&
1031    {
1032        static_assert(is_move_constructible_v<value_type>,
1033                      "optional<T>::value_or: T must be move constructible");
1034        static_assert(is_convertible_v<_Up, value_type>,
1035                      "optional<T>::value_or: U must be convertible to T");
1036        return this->has_value() ? _VSTD::move(this->__get()) :
1037                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
1038    }
1039
1040#if _LIBCPP_STD_VER > 20
1041  template<class _Func>
1042  _LIBCPP_HIDE_FROM_ABI
1043  constexpr auto and_then(_Func&& __f) & {
1044    using _Up = invoke_result_t<_Func, value_type&>;
1045    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1046                  "Result of f(value()) must be a specialization of std::optional");
1047    if (*this)
1048      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
1049    return remove_cvref_t<_Up>();
1050  }
1051
1052  template<class _Func>
1053  _LIBCPP_HIDE_FROM_ABI
1054  constexpr auto and_then(_Func&& __f) const& {
1055    using _Up = invoke_result_t<_Func, const value_type&>;
1056    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1057                  "Result of f(value()) must be a specialization of std::optional");
1058    if (*this)
1059      return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
1060    return remove_cvref_t<_Up>();
1061  }
1062
1063  template<class _Func>
1064  _LIBCPP_HIDE_FROM_ABI
1065  constexpr auto and_then(_Func&& __f) && {
1066    using _Up = invoke_result_t<_Func, value_type&&>;
1067    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1068                  "Result of f(std::move(value())) must be a specialization of std::optional");
1069    if (*this)
1070      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
1071    return remove_cvref_t<_Up>();
1072  }
1073
1074  template<class _Func>
1075  _LIBCPP_HIDE_FROM_ABI
1076  constexpr auto and_then(_Func&& __f) const&& {
1077    using _Up = invoke_result_t<_Func, const value_type&&>;
1078    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1079                  "Result of f(std::move(value())) must be a specialization of std::optional");
1080    if (*this)
1081      return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
1082    return remove_cvref_t<_Up>();
1083  }
1084
1085  template<class _Func>
1086  _LIBCPP_HIDE_FROM_ABI
1087  constexpr auto transform(_Func&& __f) & {
1088    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
1089    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
1090    static_assert(!is_same_v<_Up, in_place_t>,
1091                  "Result of f(value()) should not be std::in_place_t");
1092    static_assert(!is_same_v<_Up, nullopt_t>,
1093                  "Result of f(value()) should not be std::nullopt_t");
1094    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
1095    if (*this)
1096      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
1097    return optional<_Up>();
1098  }
1099
1100  template<class _Func>
1101  _LIBCPP_HIDE_FROM_ABI
1102  constexpr auto transform(_Func&& __f) const& {
1103    using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
1104    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
1105    static_assert(!is_same_v<_Up, in_place_t>,
1106                  "Result of f(value()) should not be std::in_place_t");
1107    static_assert(!is_same_v<_Up, nullopt_t>,
1108                  "Result of f(value()) should not be std::nullopt_t");
1109    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
1110    if (*this)
1111      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
1112    return optional<_Up>();
1113  }
1114
1115  template<class _Func>
1116  _LIBCPP_HIDE_FROM_ABI
1117  constexpr auto transform(_Func&& __f) && {
1118    using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
1119    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
1120    static_assert(!is_same_v<_Up, in_place_t>,
1121                  "Result of f(std::move(value())) should not be std::in_place_t");
1122    static_assert(!is_same_v<_Up, nullopt_t>,
1123                  "Result of f(std::move(value())) should not be std::nullopt_t");
1124    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
1125    if (*this)
1126      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
1127    return optional<_Up>();
1128  }
1129
1130  template<class _Func>
1131  _LIBCPP_HIDE_FROM_ABI
1132  constexpr auto transform(_Func&& __f) const&& {
1133    using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
1134    static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
1135    static_assert(!is_same_v<_Up, in_place_t>,
1136                  "Result of f(std::move(value())) should not be std::in_place_t");
1137    static_assert(!is_same_v<_Up, nullopt_t>,
1138                  "Result of f(std::move(value())) should not be std::nullopt_t");
1139    static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
1140    if (*this)
1141      return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
1142    return optional<_Up>();
1143  }
1144
1145  template<invocable _Func>
1146  _LIBCPP_HIDE_FROM_ABI
1147  constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
1148    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
1149                  "Result of f() should be the same type as this optional");
1150    if (*this)
1151      return *this;
1152    return _VSTD::forward<_Func>(__f)();
1153  }
1154
1155  template<invocable _Func>
1156  _LIBCPP_HIDE_FROM_ABI
1157  constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
1158    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
1159                  "Result of f() should be the same type as this optional");
1160    if (*this)
1161      return _VSTD::move(*this);
1162    return _VSTD::forward<_Func>(__f)();
1163  }
1164#endif // _LIBCPP_STD_VER > 20
1165
1166    using __base::reset;
1167};
1168
1169#if _LIBCPP_STD_VER >= 17
1170template<class _Tp>
1171    optional(_Tp) -> optional<_Tp>;
1172#endif
1173
1174// Comparisons between optionals
1175template <class _Tp, class _Up>
1176_LIBCPP_INLINE_VISIBILITY constexpr
1177enable_if_t<
1178    is_convertible_v<decltype(declval<const _Tp&>() ==
1179        declval<const _Up&>()), bool>,
1180    bool
1181>
1182operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
1183{
1184    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1185        return false;
1186    if (!static_cast<bool>(__x))
1187        return true;
1188    return *__x == *__y;
1189}
1190
1191template <class _Tp, class _Up>
1192_LIBCPP_INLINE_VISIBILITY constexpr
1193enable_if_t<
1194    is_convertible_v<decltype(declval<const _Tp&>() !=
1195        declval<const _Up&>()), bool>,
1196    bool
1197>
1198operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
1199{
1200    if (static_cast<bool>(__x) != static_cast<bool>(__y))
1201        return true;
1202    if (!static_cast<bool>(__x))
1203        return false;
1204    return *__x != *__y;
1205}
1206
1207template <class _Tp, class _Up>
1208_LIBCPP_INLINE_VISIBILITY constexpr
1209enable_if_t<
1210    is_convertible_v<decltype(declval<const _Tp&>() <
1211        declval<const _Up&>()), bool>,
1212    bool
1213>
1214operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
1215{
1216    if (!static_cast<bool>(__y))
1217        return false;
1218    if (!static_cast<bool>(__x))
1219        return true;
1220    return *__x < *__y;
1221}
1222
1223template <class _Tp, class _Up>
1224_LIBCPP_INLINE_VISIBILITY constexpr
1225enable_if_t<
1226    is_convertible_v<decltype(declval<const _Tp&>() >
1227        declval<const _Up&>()), bool>,
1228    bool
1229>
1230operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
1231{
1232    if (!static_cast<bool>(__x))
1233        return false;
1234    if (!static_cast<bool>(__y))
1235        return true;
1236    return *__x > *__y;
1237}
1238
1239template <class _Tp, class _Up>
1240_LIBCPP_INLINE_VISIBILITY constexpr
1241enable_if_t<
1242    is_convertible_v<decltype(declval<const _Tp&>() <=
1243        declval<const _Up&>()), bool>,
1244    bool
1245>
1246operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
1247{
1248    if (!static_cast<bool>(__x))
1249        return true;
1250    if (!static_cast<bool>(__y))
1251        return false;
1252    return *__x <= *__y;
1253}
1254
1255template <class _Tp, class _Up>
1256_LIBCPP_INLINE_VISIBILITY constexpr
1257enable_if_t<
1258    is_convertible_v<decltype(declval<const _Tp&>() >=
1259        declval<const _Up&>()), bool>,
1260    bool
1261>
1262operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
1263{
1264    if (!static_cast<bool>(__y))
1265        return true;
1266    if (!static_cast<bool>(__x))
1267        return false;
1268    return *__x >= *__y;
1269}
1270
1271// Comparisons with nullopt
1272template <class _Tp>
1273_LIBCPP_INLINE_VISIBILITY constexpr
1274bool
1275operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1276{
1277    return !static_cast<bool>(__x);
1278}
1279
1280template <class _Tp>
1281_LIBCPP_INLINE_VISIBILITY constexpr
1282bool
1283operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1284{
1285    return !static_cast<bool>(__x);
1286}
1287
1288template <class _Tp>
1289_LIBCPP_INLINE_VISIBILITY constexpr
1290bool
1291operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1292{
1293    return static_cast<bool>(__x);
1294}
1295
1296template <class _Tp>
1297_LIBCPP_INLINE_VISIBILITY constexpr
1298bool
1299operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1300{
1301    return static_cast<bool>(__x);
1302}
1303
1304template <class _Tp>
1305_LIBCPP_INLINE_VISIBILITY constexpr
1306bool
1307operator<(const optional<_Tp>&, nullopt_t) noexcept
1308{
1309    return false;
1310}
1311
1312template <class _Tp>
1313_LIBCPP_INLINE_VISIBILITY constexpr
1314bool
1315operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1316{
1317    return static_cast<bool>(__x);
1318}
1319
1320template <class _Tp>
1321_LIBCPP_INLINE_VISIBILITY constexpr
1322bool
1323operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1324{
1325    return !static_cast<bool>(__x);
1326}
1327
1328template <class _Tp>
1329_LIBCPP_INLINE_VISIBILITY constexpr
1330bool
1331operator<=(nullopt_t, const optional<_Tp>&) noexcept
1332{
1333    return true;
1334}
1335
1336template <class _Tp>
1337_LIBCPP_INLINE_VISIBILITY constexpr
1338bool
1339operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1340{
1341    return static_cast<bool>(__x);
1342}
1343
1344template <class _Tp>
1345_LIBCPP_INLINE_VISIBILITY constexpr
1346bool
1347operator>(nullopt_t, const optional<_Tp>&) noexcept
1348{
1349    return false;
1350}
1351
1352template <class _Tp>
1353_LIBCPP_INLINE_VISIBILITY constexpr
1354bool
1355operator>=(const optional<_Tp>&, nullopt_t) noexcept
1356{
1357    return true;
1358}
1359
1360template <class _Tp>
1361_LIBCPP_INLINE_VISIBILITY constexpr
1362bool
1363operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1364{
1365    return !static_cast<bool>(__x);
1366}
1367
1368// Comparisons with T
1369template <class _Tp, class _Up>
1370_LIBCPP_INLINE_VISIBILITY constexpr
1371enable_if_t<
1372    is_convertible_v<decltype(declval<const _Tp&>() ==
1373        declval<const _Up&>()), bool>,
1374    bool
1375>
1376operator==(const optional<_Tp>& __x, const _Up& __v)
1377{
1378    return static_cast<bool>(__x) ? *__x == __v : false;
1379}
1380
1381template <class _Tp, class _Up>
1382_LIBCPP_INLINE_VISIBILITY constexpr
1383enable_if_t<
1384    is_convertible_v<decltype(declval<const _Tp&>() ==
1385        declval<const _Up&>()), bool>,
1386    bool
1387>
1388operator==(const _Tp& __v, const optional<_Up>& __x)
1389{
1390    return static_cast<bool>(__x) ? __v == *__x : false;
1391}
1392
1393template <class _Tp, class _Up>
1394_LIBCPP_INLINE_VISIBILITY constexpr
1395enable_if_t<
1396    is_convertible_v<decltype(declval<const _Tp&>() !=
1397        declval<const _Up&>()), bool>,
1398    bool
1399>
1400operator!=(const optional<_Tp>& __x, const _Up& __v)
1401{
1402    return static_cast<bool>(__x) ? *__x != __v : true;
1403}
1404
1405template <class _Tp, class _Up>
1406_LIBCPP_INLINE_VISIBILITY constexpr
1407enable_if_t<
1408    is_convertible_v<decltype(declval<const _Tp&>() !=
1409        declval<const _Up&>()), bool>,
1410    bool
1411>
1412operator!=(const _Tp& __v, const optional<_Up>& __x)
1413{
1414    return static_cast<bool>(__x) ? __v != *__x : true;
1415}
1416
1417template <class _Tp, class _Up>
1418_LIBCPP_INLINE_VISIBILITY constexpr
1419enable_if_t<
1420    is_convertible_v<decltype(declval<const _Tp&>() <
1421        declval<const _Up&>()), bool>,
1422    bool
1423>
1424operator<(const optional<_Tp>& __x, const _Up& __v)
1425{
1426    return static_cast<bool>(__x) ? *__x < __v : true;
1427}
1428
1429template <class _Tp, class _Up>
1430_LIBCPP_INLINE_VISIBILITY constexpr
1431enable_if_t<
1432    is_convertible_v<decltype(declval<const _Tp&>() <
1433        declval<const _Up&>()), bool>,
1434    bool
1435>
1436operator<(const _Tp& __v, const optional<_Up>& __x)
1437{
1438    return static_cast<bool>(__x) ? __v < *__x : false;
1439}
1440
1441template <class _Tp, class _Up>
1442_LIBCPP_INLINE_VISIBILITY constexpr
1443enable_if_t<
1444    is_convertible_v<decltype(declval<const _Tp&>() <=
1445        declval<const _Up&>()), bool>,
1446    bool
1447>
1448operator<=(const optional<_Tp>& __x, const _Up& __v)
1449{
1450    return static_cast<bool>(__x) ? *__x <= __v : true;
1451}
1452
1453template <class _Tp, class _Up>
1454_LIBCPP_INLINE_VISIBILITY constexpr
1455enable_if_t<
1456    is_convertible_v<decltype(declval<const _Tp&>() <=
1457        declval<const _Up&>()), bool>,
1458    bool
1459>
1460operator<=(const _Tp& __v, const optional<_Up>& __x)
1461{
1462    return static_cast<bool>(__x) ? __v <= *__x : false;
1463}
1464
1465template <class _Tp, class _Up>
1466_LIBCPP_INLINE_VISIBILITY constexpr
1467enable_if_t<
1468    is_convertible_v<decltype(declval<const _Tp&>() >
1469        declval<const _Up&>()), bool>,
1470    bool
1471>
1472operator>(const optional<_Tp>& __x, const _Up& __v)
1473{
1474    return static_cast<bool>(__x) ? *__x > __v : false;
1475}
1476
1477template <class _Tp, class _Up>
1478_LIBCPP_INLINE_VISIBILITY constexpr
1479enable_if_t<
1480    is_convertible_v<decltype(declval<const _Tp&>() >
1481        declval<const _Up&>()), bool>,
1482    bool
1483>
1484operator>(const _Tp& __v, const optional<_Up>& __x)
1485{
1486    return static_cast<bool>(__x) ? __v > *__x : true;
1487}
1488
1489template <class _Tp, class _Up>
1490_LIBCPP_INLINE_VISIBILITY constexpr
1491enable_if_t<
1492    is_convertible_v<decltype(declval<const _Tp&>() >=
1493        declval<const _Up&>()), bool>,
1494    bool
1495>
1496operator>=(const optional<_Tp>& __x, const _Up& __v)
1497{
1498    return static_cast<bool>(__x) ? *__x >= __v : false;
1499}
1500
1501template <class _Tp, class _Up>
1502_LIBCPP_INLINE_VISIBILITY constexpr
1503enable_if_t<
1504    is_convertible_v<decltype(declval<const _Tp&>() >=
1505        declval<const _Up&>()), bool>,
1506    bool
1507>
1508operator>=(const _Tp& __v, const optional<_Up>& __x)
1509{
1510    return static_cast<bool>(__x) ? __v >= *__x : true;
1511}
1512
1513
1514template <class _Tp>
1515inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
1516enable_if_t<
1517    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1518    void
1519>
1520swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1521{
1522    __x.swap(__y);
1523}
1524
1525template <class _Tp>
1526_LIBCPP_INLINE_VISIBILITY constexpr
1527optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1528{
1529    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1530}
1531
1532template <class _Tp, class... _Args>
1533_LIBCPP_INLINE_VISIBILITY constexpr
1534optional<_Tp> make_optional(_Args&&... __args)
1535{
1536    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1537}
1538
1539template <class _Tp, class _Up, class... _Args>
1540_LIBCPP_INLINE_VISIBILITY constexpr
1541optional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
1542{
1543    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1544}
1545
1546template <class _Tp>
1547struct _LIBCPP_TEMPLATE_VIS hash<
1548    __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1549>
1550{
1551#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1552    _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1553    _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t        result_type;
1554#endif
1555
1556    _LIBCPP_INLINE_VISIBILITY
1557    size_t operator()(const optional<_Tp>& __opt) const
1558    {
1559        return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
1560    }
1561};
1562
1563_LIBCPP_END_NAMESPACE_STD
1564
1565#endif // _LIBCPP_STD_VER > 14
1566
1567#endif // _LIBCPP_OPTIONAL
1568