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