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