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