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