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