1261272Sdim// -*- C++ -*-
2261272Sdim//===-------------------------- optional ----------------------------------===//
3261272Sdim//
4261272Sdim//                     The LLVM Compiler Infrastructure
5261272Sdim//
6261272Sdim// This file is dual licensed under the MIT and the University of Illinois Open
7261272Sdim// Source Licenses. See LICENSE.TXT for details.
8261272Sdim//
9261272Sdim//===----------------------------------------------------------------------===//
10261272Sdim
11261272Sdim#ifndef _LIBCPP_OPTIONAL
12261272Sdim#define _LIBCPP_OPTIONAL
13261272Sdim
14261272Sdim/*
15261272Sdim    optional synopsis
16261272Sdim
17261272Sdim// C++1y
18261272Sdim
19276792Sdimnamespace std { namespace experimental { inline namespace fundamentals_v1 {
20261272Sdim
21276792Sdim    // 5.3, optional for object types
22276792Sdim    template <class T> class optional;
23261272Sdim
24276792Sdim    // 5.4, In-place construction
25276792Sdim    struct in_place_t{};
26276792Sdim    constexpr in_place_t in_place{};
27261272Sdim
28276792Sdim    // 5.5, No-value state indicator
29276792Sdim    struct nullopt_t{see below};
30276792Sdim    constexpr nullopt_t nullopt(unspecified);
31261272Sdim
32276792Sdim    // 5.6, Class bad_optional_access
33276792Sdim    class bad_optional_access;
34261272Sdim
35276792Sdim    // 5.7, Relational operators
36276792Sdim    template <class T>
37276792Sdim      constexpr bool operator==(const optional<T>&, const optional<T>&);
38276792Sdim    template <class T>
39276792Sdim      constexpr bool operator!=(const optional<T>&, const optional<T>&);
40276792Sdim    template <class T>
41276792Sdim      constexpr bool operator<(const optional<T>&, const optional<T>&);
42276792Sdim    template <class T>
43276792Sdim      constexpr bool operator>(const optional<T>&, const optional<T>&);
44276792Sdim    template <class T>
45276792Sdim      constexpr bool operator<=(const optional<T>&, const optional<T>&);
46276792Sdim    template <class T>
47276792Sdim      constexpr bool operator>=(const optional<T>&, const optional<T>&);
48261272Sdim
49276792Sdim    // 5.8, Comparison with nullopt
50276792Sdim    template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
51276792Sdim    template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
52276792Sdim    template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
53276792Sdim    template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
54276792Sdim    template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
55276792Sdim    template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
56276792Sdim    template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
57276792Sdim    template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
58276792Sdim    template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
59276792Sdim    template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
60276792Sdim    template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
61276792Sdim    template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
62261272Sdim
63276792Sdim    // 5.9, Comparison with T
64276792Sdim    template <class T> constexpr bool operator==(const optional<T>&, const T&);
65276792Sdim    template <class T> constexpr bool operator==(const T&, const optional<T>&);
66276792Sdim    template <class T> constexpr bool operator!=(const optional<T>&, const T&);
67276792Sdim    template <class T> constexpr bool operator!=(const T&, const optional<T>&);
68276792Sdim    template <class T> constexpr bool operator<(const optional<T>&, const T&);
69276792Sdim    template <class T> constexpr bool operator<(const T&, const optional<T>&);
70276792Sdim    template <class T> constexpr bool operator<=(const optional<T>&, const T&);
71276792Sdim    template <class T> constexpr bool operator<=(const T&, const optional<T>&);
72276792Sdim    template <class T> constexpr bool operator>(const optional<T>&, const T&);
73276792Sdim    template <class T> constexpr bool operator>(const T&, const optional<T>&);
74276792Sdim    template <class T> constexpr bool operator>=(const optional<T>&, const T&);
75276792Sdim    template <class T> constexpr bool operator>=(const T&, const optional<T>&);
76261272Sdim
77276792Sdim    // 5.10, Specialized algorithms
78276792Sdim    template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
79276792Sdim    template <class T> constexpr optional<see below> make_optional(T&&);
80261272Sdim
81276792Sdim	template <class T>
82276792Sdim	class optional
83276792Sdim	{
84276792Sdim	public:
85276792Sdim	  typedef T value_type;
86261272Sdim
87276792Sdim	  // 5.3.1, Constructors
88276792Sdim	  constexpr optional() noexcept;
89276792Sdim	  constexpr optional(nullopt_t) noexcept;
90276792Sdim	  optional(const optional&);
91276792Sdim	  optional(optional&&) noexcept(see below);
92276792Sdim	  constexpr optional(const T&);
93276792Sdim	  constexpr optional(T&&);
94276792Sdim	  template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
95276792Sdim	  template <class U, class... Args>
96276792Sdim		constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
97261272Sdim
98276792Sdim	  // 5.3.2, Destructor
99276792Sdim	  ~optional();
100261272Sdim
101276792Sdim	  // 5.3.3, Assignment
102276792Sdim	  optional& operator=(nullopt_t) noexcept;
103276792Sdim	  optional& operator=(const optional&);
104276792Sdim	  optional& operator=(optional&&) noexcept(see below);
105276792Sdim	  template <class U> optional& operator=(U&&);
106276792Sdim	  template <class... Args> void emplace(Args&&...);
107276792Sdim	  template <class U, class... Args>
108276792Sdim		void emplace(initializer_list<U>, Args&&...);
109261272Sdim
110276792Sdim	  // 5.3.4, Swap
111276792Sdim	  void swap(optional&) noexcept(see below);
112261272Sdim
113276792Sdim	  // 5.3.5, Observers
114276792Sdim	  constexpr T const* operator ->() const;
115276792Sdim	  constexpr T* operator ->();
116276792Sdim	  constexpr T const& operator *() const &;
117276792Sdim	  constexpr T& operator *() &;
118276792Sdim	  constexpr T&& operator *() &&;
119276792Sdim	  constexpr const T&& operator *() const &&;
120276792Sdim	  constexpr explicit operator bool() const noexcept;
121276792Sdim	  constexpr T const& value() const &;
122276792Sdim	  constexpr T& value() &;
123276792Sdim	  constexpr T&& value() &&;
124276792Sdim	  constexpr const T&& value() const &&;
125276792Sdim	  template <class U> constexpr T value_or(U&&) const &;
126276792Sdim	  template <class U> constexpr T value_or(U&&) &&;
127261272Sdim
128276792Sdim	private:
129276792Sdim	  T*   val;  // exposition only
130276792Sdim	};
131261272Sdim
132276792Sdim  } // namespace fundamentals_v1
133276792Sdim  } // namespace experimental
134261272Sdim
135276792Sdim  // 5.11, Hash support
136276792Sdim  template <class T> struct hash;
137276792Sdim  template <class T> struct hash<experimental::optional<T>>;
138276792Sdim
139276792Sdim} // namespace std
140276792Sdim
141261272Sdim*/
142261272Sdim
143276792Sdim#include <experimental/__config>
144261272Sdim#include <functional>
145261272Sdim#include <stdexcept>
146261272Sdim
147276792Sdim_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
148261272Sdimclass _LIBCPP_EXCEPTION_ABI bad_optional_access
149276792Sdim    : public std::logic_error
150261272Sdim{
151261272Sdimpublic:
152276792Sdim	bad_optional_access() : std::logic_error("Bad optional Access") {}
153276792Sdim
154276792Sdim//	Get the key function ~bad_optional_access() into the dylib
155261272Sdim    virtual ~bad_optional_access() _NOEXCEPT;
156261272Sdim};
157261272Sdim
158276792Sdim_LIBCPP_END_NAMESPACE_EXPERIMENTAL
159261272Sdim
160276792Sdim
161261272Sdim#if _LIBCPP_STD_VER > 11
162261272Sdim
163261272Sdim#include <initializer_list>
164261272Sdim#include <type_traits>
165261272Sdim#include <new>
166261272Sdim#include <__functional_base>
167261272Sdim#include <__undef_min_max>
168276792Sdim#include <__debug>
169261272Sdim
170261272Sdim#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
171261272Sdim#pragma GCC system_header
172261272Sdim#endif
173261272Sdim
174276792Sdim_LIBCPP_BEGIN_NAMESPACE_LFTS
175261272Sdim
176261272Sdimstruct in_place_t {};
177261272Sdimconstexpr in_place_t in_place{};
178261272Sdim
179261272Sdimstruct nullopt_t
180261272Sdim{
181261272Sdim    explicit constexpr nullopt_t(int) noexcept {}
182261272Sdim};
183261272Sdim
184261272Sdimconstexpr nullopt_t nullopt{0};
185261272Sdim
186261272Sdimtemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
187261272Sdimclass __optional_storage
188261272Sdim{
189261272Sdimprotected:
190261272Sdim    typedef _Tp value_type;
191261272Sdim    union
192261272Sdim    {
193261272Sdim        char __null_state_;
194261272Sdim        value_type __val_;
195261272Sdim    };
196261272Sdim    bool __engaged_ = false;
197261272Sdim
198261272Sdim    _LIBCPP_INLINE_VISIBILITY
199261272Sdim    ~__optional_storage()
200261272Sdim    {
201261272Sdim        if (__engaged_)
202261272Sdim            __val_.~value_type();
203261272Sdim    }
204261272Sdim
205261272Sdim    _LIBCPP_INLINE_VISIBILITY
206261272Sdim    constexpr __optional_storage() noexcept
207261272Sdim        :  __null_state_('\0') {}
208261272Sdim
209261272Sdim    _LIBCPP_INLINE_VISIBILITY
210261272Sdim    __optional_storage(const __optional_storage& __x)
211261272Sdim        :  __engaged_(__x.__engaged_)
212261272Sdim        {
213261272Sdim            if (__engaged_)
214261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
215261272Sdim        }
216261272Sdim
217261272Sdim    _LIBCPP_INLINE_VISIBILITY
218261272Sdim    __optional_storage(__optional_storage&& __x)
219261272Sdim                      noexcept(is_nothrow_move_constructible<value_type>::value)
220261272Sdim        :  __engaged_(__x.__engaged_)
221261272Sdim        {
222261272Sdim            if (__engaged_)
223261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
224261272Sdim        }
225261272Sdim
226261272Sdim    _LIBCPP_INLINE_VISIBILITY
227261272Sdim    constexpr __optional_storage(const value_type& __v)
228261272Sdim        :  __val_(__v),
229261272Sdim           __engaged_(true) {}
230261272Sdim
231261272Sdim    _LIBCPP_INLINE_VISIBILITY
232261272Sdim    constexpr __optional_storage(value_type&& __v)
233261272Sdim        :  __val_(_VSTD::move(__v)),
234261272Sdim           __engaged_(true) {}
235261272Sdim
236261272Sdim    template <class... _Args>
237261272Sdim    _LIBCPP_INLINE_VISIBILITY
238261272Sdim    constexpr
239261272Sdim    explicit __optional_storage(in_place_t, _Args&&... __args)
240261272Sdim       :  __val_(_VSTD::forward<_Args>(__args)...),
241261272Sdim           __engaged_(true) {}
242261272Sdim};
243261272Sdim
244261272Sdimtemplate <class _Tp>
245261272Sdimclass __optional_storage<_Tp, true>
246261272Sdim{
247261272Sdimprotected:
248261272Sdim    typedef _Tp value_type;
249261272Sdim    union
250261272Sdim    {
251261272Sdim        char __null_state_;
252261272Sdim        value_type __val_;
253261272Sdim    };
254261272Sdim    bool __engaged_ = false;
255261272Sdim
256261272Sdim    _LIBCPP_INLINE_VISIBILITY
257261272Sdim    constexpr __optional_storage() noexcept
258261272Sdim        :  __null_state_('\0') {}
259261272Sdim
260261272Sdim    _LIBCPP_INLINE_VISIBILITY
261261272Sdim    __optional_storage(const __optional_storage& __x)
262261272Sdim        :  __engaged_(__x.__engaged_)
263261272Sdim        {
264261272Sdim            if (__engaged_)
265261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
266261272Sdim        }
267261272Sdim
268261272Sdim    _LIBCPP_INLINE_VISIBILITY
269261272Sdim    __optional_storage(__optional_storage&& __x)
270261272Sdim                      noexcept(is_nothrow_move_constructible<value_type>::value)
271261272Sdim        :  __engaged_(__x.__engaged_)
272261272Sdim        {
273261272Sdim            if (__engaged_)
274261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
275261272Sdim        }
276261272Sdim
277261272Sdim    _LIBCPP_INLINE_VISIBILITY
278261272Sdim    constexpr __optional_storage(const value_type& __v)
279261272Sdim        :  __val_(__v),
280261272Sdim           __engaged_(true) {}
281261272Sdim
282261272Sdim    _LIBCPP_INLINE_VISIBILITY
283261272Sdim    constexpr __optional_storage(value_type&& __v)
284261272Sdim        :  __val_(_VSTD::move(__v)),
285261272Sdim           __engaged_(true) {}
286261272Sdim
287261272Sdim    template <class... _Args>
288261272Sdim    _LIBCPP_INLINE_VISIBILITY
289261272Sdim    constexpr
290261272Sdim    explicit __optional_storage(in_place_t, _Args&&... __args)
291261272Sdim       :  __val_(_VSTD::forward<_Args>(__args)...),
292261272Sdim           __engaged_(true) {}
293261272Sdim};
294261272Sdim
295261272Sdimtemplate <class _Tp>
296261272Sdimclass optional
297261272Sdim    : private __optional_storage<_Tp>
298261272Sdim{
299261272Sdim    typedef __optional_storage<_Tp> __base;
300261272Sdimpublic:
301261272Sdim    typedef _Tp value_type;
302261272Sdim
303261272Sdim    static_assert(!is_reference<value_type>::value,
304261272Sdim              "Instantiation of optional with a reference type is ill-formed.");
305261272Sdim    static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
306261272Sdim              "Instantiation of optional with a in_place_t type is ill-formed.");
307261272Sdim    static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
308261272Sdim              "Instantiation of optional with a nullopt_t type is ill-formed.");
309261272Sdim    static_assert(is_object<value_type>::value,
310261272Sdim        "Instantiation of optional with a non-object type is undefined behavior.");
311261272Sdim    static_assert(is_nothrow_destructible<value_type>::value,
312261272Sdim        "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
313261272Sdim
314261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
315261272Sdim    _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
316261272Sdim    _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
317261272Sdim    _LIBCPP_INLINE_VISIBILITY ~optional() = default;
318261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
319261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
320261272Sdim        : __base(__v) {}
321261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
322261272Sdim        : __base(_VSTD::move(__v)) {}
323261272Sdim
324261272Sdim    template <class... _Args,
325261272Sdim              class = typename enable_if
326261272Sdim                      <
327261272Sdim                           is_constructible<value_type, _Args...>::value
328261272Sdim                      >::type
329261272Sdim             >
330261272Sdim    _LIBCPP_INLINE_VISIBILITY
331261272Sdim    constexpr
332261272Sdim    explicit optional(in_place_t, _Args&&... __args)
333261272Sdim        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
334261272Sdim
335261272Sdim    template <class _Up, class... _Args,
336261272Sdim              class = typename enable_if
337261272Sdim                      <
338261272Sdim                           is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
339261272Sdim                      >::type
340261272Sdim             >
341261272Sdim    _LIBCPP_INLINE_VISIBILITY
342261272Sdim    constexpr
343261272Sdim    explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
344261272Sdim        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
345261272Sdim
346261272Sdim    _LIBCPP_INLINE_VISIBILITY
347261272Sdim    optional& operator=(nullopt_t) noexcept
348261272Sdim    {
349261272Sdim        if (this->__engaged_)
350261272Sdim        {
351261272Sdim            this->__val_.~value_type();
352261272Sdim            this->__engaged_ = false;
353261272Sdim        }
354261272Sdim        return *this;
355261272Sdim    }
356261272Sdim
357261272Sdim    _LIBCPP_INLINE_VISIBILITY
358261272Sdim    optional&
359261272Sdim    operator=(const optional& __opt)
360261272Sdim    {
361261272Sdim        if (this->__engaged_ == __opt.__engaged_)
362261272Sdim        {
363261272Sdim            if (this->__engaged_)
364261272Sdim                this->__val_ = __opt.__val_;
365261272Sdim        }
366261272Sdim        else
367261272Sdim        {
368261272Sdim            if (this->__engaged_)
369261272Sdim                this->__val_.~value_type();
370261272Sdim            else
371261272Sdim                ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
372261272Sdim            this->__engaged_ = __opt.__engaged_;
373261272Sdim        }
374261272Sdim        return *this;
375261272Sdim    }
376261272Sdim
377261272Sdim    _LIBCPP_INLINE_VISIBILITY
378261272Sdim    optional&
379261272Sdim    operator=(optional&& __opt)
380261272Sdim        noexcept(is_nothrow_move_assignable<value_type>::value &&
381261272Sdim                 is_nothrow_move_constructible<value_type>::value)
382261272Sdim    {
383261272Sdim        if (this->__engaged_ == __opt.__engaged_)
384261272Sdim        {
385261272Sdim            if (this->__engaged_)
386261272Sdim                this->__val_ = _VSTD::move(__opt.__val_);
387261272Sdim        }
388261272Sdim        else
389261272Sdim        {
390261272Sdim            if (this->__engaged_)
391261272Sdim                this->__val_.~value_type();
392261272Sdim            else
393261272Sdim                ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
394261272Sdim            this->__engaged_ = __opt.__engaged_;
395261272Sdim        }
396261272Sdim        return *this;
397261272Sdim    }
398261272Sdim
399261272Sdim    template <class _Up,
400261272Sdim              class = typename enable_if
401261272Sdim                      <
402261272Sdim                          is_same<typename remove_reference<_Up>::type, value_type>::value &&
403261272Sdim                          is_constructible<value_type, _Up>::value &&
404261272Sdim                          is_assignable<value_type&, _Up>::value
405261272Sdim                      >::type
406261272Sdim             >
407261272Sdim    _LIBCPP_INLINE_VISIBILITY
408261272Sdim    optional&
409261272Sdim    operator=(_Up&& __v)
410261272Sdim    {
411261272Sdim        if (this->__engaged_)
412261272Sdim            this->__val_ = _VSTD::forward<_Up>(__v);
413261272Sdim        else
414261272Sdim        {
415261272Sdim            ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
416261272Sdim            this->__engaged_ = true;
417261272Sdim        }
418261272Sdim        return *this;
419261272Sdim    }
420261272Sdim
421261272Sdim    template <class... _Args,
422261272Sdim              class = typename enable_if
423261272Sdim                      <
424261272Sdim                          is_constructible<value_type, _Args...>::value
425261272Sdim                      >::type
426261272Sdim             >
427261272Sdim    _LIBCPP_INLINE_VISIBILITY
428261272Sdim    void
429261272Sdim    emplace(_Args&&... __args)
430261272Sdim    {
431261272Sdim        *this = nullopt;
432261272Sdim        ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
433261272Sdim        this->__engaged_ = true;
434261272Sdim    }
435261272Sdim
436261272Sdim    template <class _Up, class... _Args,
437261272Sdim              class = typename enable_if
438261272Sdim                      <
439261272Sdim                          is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
440261272Sdim                      >::type
441261272Sdim             >
442261272Sdim    _LIBCPP_INLINE_VISIBILITY
443261272Sdim    void
444261272Sdim    emplace(initializer_list<_Up> __il, _Args&&... __args)
445261272Sdim    {
446261272Sdim        *this = nullopt;
447261272Sdim        ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
448261272Sdim        this->__engaged_ = true;
449261272Sdim    }
450261272Sdim
451261272Sdim    _LIBCPP_INLINE_VISIBILITY
452261272Sdim    void
453261272Sdim    swap(optional& __opt)
454261272Sdim        noexcept(is_nothrow_move_constructible<value_type>::value &&
455261272Sdim                 __is_nothrow_swappable<value_type>::value)
456261272Sdim    {
457261272Sdim        using _VSTD::swap;
458261272Sdim        if (this->__engaged_ == __opt.__engaged_)
459261272Sdim        {
460261272Sdim            if (this->__engaged_)
461261272Sdim                swap(this->__val_, __opt.__val_);
462261272Sdim        }
463261272Sdim        else
464261272Sdim        {
465261272Sdim            if (this->__engaged_)
466261272Sdim            {
467261272Sdim                ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
468261272Sdim                this->__val_.~value_type();
469261272Sdim            }
470261272Sdim            else
471261272Sdim            {
472261272Sdim                ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
473261272Sdim                __opt.__val_.~value_type();
474261272Sdim            }
475261272Sdim            swap(this->__engaged_, __opt.__engaged_);
476261272Sdim        }
477261272Sdim    }
478261272Sdim
479261272Sdim    _LIBCPP_INLINE_VISIBILITY
480261272Sdim    constexpr
481261272Sdim    value_type const*
482261272Sdim    operator->() const
483261272Sdim    {
484261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
485261272Sdim        return __operator_arrow(__has_operator_addressof<value_type>{});
486261272Sdim    }
487261272Sdim
488261272Sdim    _LIBCPP_INLINE_VISIBILITY
489261272Sdim    value_type*
490261272Sdim    operator->()
491261272Sdim    {
492261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
493261272Sdim        return _VSTD::addressof(this->__val_);
494261272Sdim    }
495261272Sdim
496261272Sdim    _LIBCPP_INLINE_VISIBILITY
497261272Sdim    constexpr
498261272Sdim    const value_type&
499261272Sdim    operator*() const
500261272Sdim    {
501261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
502261272Sdim        return this->__val_;
503261272Sdim    }
504261272Sdim
505261272Sdim    _LIBCPP_INLINE_VISIBILITY
506261272Sdim    value_type&
507261272Sdim    operator*()
508261272Sdim    {
509261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
510261272Sdim        return this->__val_;
511261272Sdim    }
512261272Sdim
513261272Sdim    _LIBCPP_INLINE_VISIBILITY
514261272Sdim    constexpr explicit operator bool() const noexcept {return this->__engaged_;}
515261272Sdim
516261272Sdim    _LIBCPP_INLINE_VISIBILITY
517261272Sdim    constexpr value_type const& value() const
518261272Sdim    {
519261272Sdim        if (!this->__engaged_)
520276792Sdim            throw bad_optional_access();
521261272Sdim        return this->__val_;
522261272Sdim    }
523261272Sdim
524261272Sdim    _LIBCPP_INLINE_VISIBILITY
525261272Sdim    value_type& value()
526261272Sdim    {
527261272Sdim        if (!this->__engaged_)
528276792Sdim            throw bad_optional_access();
529261272Sdim        return this->__val_;
530261272Sdim    }
531261272Sdim
532261272Sdim    template <class _Up>
533261272Sdim    _LIBCPP_INLINE_VISIBILITY
534261272Sdim    constexpr value_type value_or(_Up&& __v) const&
535261272Sdim    {
536261272Sdim        static_assert(is_copy_constructible<value_type>::value,
537261272Sdim                      "optional<T>::value_or: T must be copy constructible");
538261272Sdim        static_assert(is_convertible<_Up, value_type>::value,
539261272Sdim                      "optional<T>::value_or: U must be convertible to T");
540261272Sdim        return this->__engaged_ ? this->__val_ :
541261272Sdim                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
542261272Sdim    }
543261272Sdim
544261272Sdim    template <class _Up>
545261272Sdim    _LIBCPP_INLINE_VISIBILITY
546261272Sdim    value_type value_or(_Up&& __v) &&
547261272Sdim    {
548261272Sdim        static_assert(is_move_constructible<value_type>::value,
549261272Sdim                      "optional<T>::value_or: T must be move constructible");
550261272Sdim        static_assert(is_convertible<_Up, value_type>::value,
551261272Sdim                      "optional<T>::value_or: U must be convertible to T");
552261272Sdim        return this->__engaged_ ? _VSTD::move(this->__val_) :
553261272Sdim                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
554261272Sdim    }
555261272Sdim
556261272Sdimprivate:
557261272Sdim    _LIBCPP_INLINE_VISIBILITY
558261272Sdim    value_type const*
559261272Sdim    __operator_arrow(true_type) const
560261272Sdim    {
561261272Sdim        return _VSTD::addressof(this->__val_);
562261272Sdim    }
563261272Sdim
564261272Sdim    _LIBCPP_INLINE_VISIBILITY
565261272Sdim    constexpr
566261272Sdim    value_type const*
567261272Sdim    __operator_arrow(false_type) const
568261272Sdim    {
569261272Sdim        return &this->__val_;
570261272Sdim    }
571261272Sdim};
572261272Sdim
573276792Sdim// Comparisons between optionals
574261272Sdimtemplate <class _Tp>
575261272Sdiminline _LIBCPP_INLINE_VISIBILITY
576261272Sdimconstexpr
577261272Sdimbool
578261272Sdimoperator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
579261272Sdim{
580261272Sdim    if (static_cast<bool>(__x) != static_cast<bool>(__y))
581261272Sdim        return false;
582261272Sdim    if (!static_cast<bool>(__x))
583261272Sdim        return true;
584261272Sdim    return *__x == *__y;
585261272Sdim}
586261272Sdim
587261272Sdimtemplate <class _Tp>
588261272Sdiminline _LIBCPP_INLINE_VISIBILITY
589261272Sdimconstexpr
590261272Sdimbool
591276792Sdimoperator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
592276792Sdim{
593276792Sdim    return !(__x == __y);
594276792Sdim}
595276792Sdim
596276792Sdimtemplate <class _Tp>
597276792Sdiminline _LIBCPP_INLINE_VISIBILITY
598276792Sdimconstexpr
599276792Sdimbool
600261272Sdimoperator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
601261272Sdim{
602261272Sdim    if (!static_cast<bool>(__y))
603261272Sdim        return false;
604261272Sdim    if (!static_cast<bool>(__x))
605261272Sdim        return true;
606276792Sdim    return *__x < *__y;
607261272Sdim}
608261272Sdim
609261272Sdimtemplate <class _Tp>
610261272Sdiminline _LIBCPP_INLINE_VISIBILITY
611261272Sdimconstexpr
612261272Sdimbool
613276792Sdimoperator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
614276792Sdim{
615276792Sdim    return __y < __x;
616276792Sdim}
617276792Sdim
618276792Sdimtemplate <class _Tp>
619276792Sdiminline _LIBCPP_INLINE_VISIBILITY
620276792Sdimconstexpr
621276792Sdimbool
622276792Sdimoperator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
623276792Sdim{
624276792Sdim    return !(__y < __x);
625276792Sdim}
626276792Sdim
627276792Sdimtemplate <class _Tp>
628276792Sdiminline _LIBCPP_INLINE_VISIBILITY
629276792Sdimconstexpr
630276792Sdimbool
631276792Sdimoperator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
632276792Sdim{
633276792Sdim    return !(__x < __y);
634276792Sdim}
635276792Sdim
636276792Sdim
637276792Sdim// Comparisons with nullopt
638276792Sdimtemplate <class _Tp>
639276792Sdiminline _LIBCPP_INLINE_VISIBILITY
640276792Sdimconstexpr
641276792Sdimbool
642261272Sdimoperator==(const optional<_Tp>& __x, nullopt_t) noexcept
643261272Sdim{
644261272Sdim    return !static_cast<bool>(__x);
645261272Sdim}
646261272Sdim
647261272Sdimtemplate <class _Tp>
648261272Sdiminline _LIBCPP_INLINE_VISIBILITY
649261272Sdimconstexpr
650261272Sdimbool
651261272Sdimoperator==(nullopt_t, const optional<_Tp>& __x) noexcept
652261272Sdim{
653261272Sdim    return !static_cast<bool>(__x);
654261272Sdim}
655261272Sdim
656261272Sdimtemplate <class _Tp>
657261272Sdiminline _LIBCPP_INLINE_VISIBILITY
658261272Sdimconstexpr
659261272Sdimbool
660276792Sdimoperator!=(const optional<_Tp>& __x, nullopt_t) noexcept
661276792Sdim{
662276792Sdim    return static_cast<bool>(__x);
663276792Sdim}
664276792Sdim
665276792Sdimtemplate <class _Tp>
666276792Sdiminline _LIBCPP_INLINE_VISIBILITY
667276792Sdimconstexpr
668276792Sdimbool
669276792Sdimoperator!=(nullopt_t, const optional<_Tp>& __x) noexcept
670276792Sdim{
671276792Sdim    return static_cast<bool>(__x);
672276792Sdim}
673276792Sdim
674276792Sdimtemplate <class _Tp>
675276792Sdiminline _LIBCPP_INLINE_VISIBILITY
676276792Sdimconstexpr
677276792Sdimbool
678261272Sdimoperator<(const optional<_Tp>&, nullopt_t) noexcept
679261272Sdim{
680261272Sdim    return false;
681261272Sdim}
682261272Sdim
683261272Sdimtemplate <class _Tp>
684261272Sdiminline _LIBCPP_INLINE_VISIBILITY
685261272Sdimconstexpr
686261272Sdimbool
687261272Sdimoperator<(nullopt_t, const optional<_Tp>& __x) noexcept
688261272Sdim{
689261272Sdim    return static_cast<bool>(__x);
690261272Sdim}
691261272Sdim
692261272Sdimtemplate <class _Tp>
693261272Sdiminline _LIBCPP_INLINE_VISIBILITY
694261272Sdimconstexpr
695261272Sdimbool
696276792Sdimoperator<=(const optional<_Tp>& __x, nullopt_t) noexcept
697276792Sdim{
698276792Sdim    return !static_cast<bool>(__x);
699276792Sdim}
700276792Sdim
701276792Sdimtemplate <class _Tp>
702276792Sdiminline _LIBCPP_INLINE_VISIBILITY
703276792Sdimconstexpr
704276792Sdimbool
705276792Sdimoperator<=(nullopt_t, const optional<_Tp>& __x) noexcept
706276792Sdim{
707276792Sdim    return true;
708276792Sdim}
709276792Sdim
710276792Sdimtemplate <class _Tp>
711276792Sdiminline _LIBCPP_INLINE_VISIBILITY
712276792Sdimconstexpr
713276792Sdimbool
714276792Sdimoperator>(const optional<_Tp>& __x, nullopt_t) noexcept
715276792Sdim{
716276792Sdim    return static_cast<bool>(__x);
717276792Sdim}
718276792Sdim
719276792Sdimtemplate <class _Tp>
720276792Sdiminline _LIBCPP_INLINE_VISIBILITY
721276792Sdimconstexpr
722276792Sdimbool
723276792Sdimoperator>(nullopt_t, const optional<_Tp>& __x) noexcept
724276792Sdim{
725276792Sdim    return false;
726276792Sdim}
727276792Sdim
728276792Sdimtemplate <class _Tp>
729276792Sdiminline _LIBCPP_INLINE_VISIBILITY
730276792Sdimconstexpr
731276792Sdimbool
732276792Sdimoperator>=(const optional<_Tp>&, nullopt_t) noexcept
733276792Sdim{
734276792Sdim    return true;
735276792Sdim}
736276792Sdim
737276792Sdimtemplate <class _Tp>
738276792Sdiminline _LIBCPP_INLINE_VISIBILITY
739276792Sdimconstexpr
740276792Sdimbool
741276792Sdimoperator>=(nullopt_t, const optional<_Tp>& __x) noexcept
742276792Sdim{
743276792Sdim    return !static_cast<bool>(__x);
744276792Sdim}
745276792Sdim
746276792Sdim// Comparisons with T
747276792Sdimtemplate <class _Tp>
748276792Sdiminline _LIBCPP_INLINE_VISIBILITY
749276792Sdimconstexpr
750276792Sdimbool
751261272Sdimoperator==(const optional<_Tp>& __x, const _Tp& __v)
752261272Sdim{
753261272Sdim    return static_cast<bool>(__x) ? *__x == __v : false;
754261272Sdim}
755261272Sdim
756261272Sdimtemplate <class _Tp>
757261272Sdiminline _LIBCPP_INLINE_VISIBILITY
758261272Sdimconstexpr
759261272Sdimbool
760261272Sdimoperator==(const _Tp& __v, const optional<_Tp>& __x)
761261272Sdim{
762261272Sdim    return static_cast<bool>(__x) ? *__x == __v : false;
763261272Sdim}
764261272Sdim
765261272Sdimtemplate <class _Tp>
766261272Sdiminline _LIBCPP_INLINE_VISIBILITY
767261272Sdimconstexpr
768261272Sdimbool
769276792Sdimoperator!=(const optional<_Tp>& __x, const _Tp& __v)
770276792Sdim{
771276792Sdim    return static_cast<bool>(__x) ? !(*__x == __v) : true;
772276792Sdim}
773276792Sdim
774276792Sdimtemplate <class _Tp>
775276792Sdiminline _LIBCPP_INLINE_VISIBILITY
776276792Sdimconstexpr
777276792Sdimbool
778276792Sdimoperator!=(const _Tp& __v, const optional<_Tp>& __x)
779276792Sdim{
780276792Sdim    return static_cast<bool>(__x) ? !(*__x == __v) : true;
781276792Sdim}
782276792Sdim
783276792Sdimtemplate <class _Tp>
784276792Sdiminline _LIBCPP_INLINE_VISIBILITY
785276792Sdimconstexpr
786276792Sdimbool
787261272Sdimoperator<(const optional<_Tp>& __x, const _Tp& __v)
788261272Sdim{
789261272Sdim    return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
790261272Sdim}
791261272Sdim
792261272Sdimtemplate <class _Tp>
793261272Sdiminline _LIBCPP_INLINE_VISIBILITY
794261272Sdimconstexpr
795261272Sdimbool
796261272Sdimoperator<(const _Tp& __v, const optional<_Tp>& __x)
797261272Sdim{
798261272Sdim    return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
799261272Sdim}
800261272Sdim
801261272Sdimtemplate <class _Tp>
802261272Sdiminline _LIBCPP_INLINE_VISIBILITY
803276792Sdimconstexpr
804276792Sdimbool
805276792Sdimoperator<=(const optional<_Tp>& __x, const _Tp& __v)
806276792Sdim{
807276792Sdim    return !(__x > __v);
808276792Sdim}
809276792Sdim
810276792Sdimtemplate <class _Tp>
811276792Sdiminline _LIBCPP_INLINE_VISIBILITY
812276792Sdimconstexpr
813276792Sdimbool
814276792Sdimoperator<=(const _Tp& __v, const optional<_Tp>& __x)
815276792Sdim{
816276792Sdim    return !(__v > __x);
817276792Sdim}
818276792Sdim
819276792Sdimtemplate <class _Tp>
820276792Sdiminline _LIBCPP_INLINE_VISIBILITY
821276792Sdimconstexpr
822276792Sdimbool
823276792Sdimoperator>(const optional<_Tp>& __x, const _Tp& __v)
824276792Sdim{
825276792Sdim    return static_cast<bool>(__x) ? __v < __x : false;
826276792Sdim}
827276792Sdim
828276792Sdimtemplate <class _Tp>
829276792Sdiminline _LIBCPP_INLINE_VISIBILITY
830276792Sdimconstexpr
831276792Sdimbool
832276792Sdimoperator>(const _Tp& __v, const optional<_Tp>& __x)
833276792Sdim{
834276792Sdim    return static_cast<bool>(__x) ? __x < __v : true;
835276792Sdim}
836276792Sdim
837276792Sdimtemplate <class _Tp>
838276792Sdiminline _LIBCPP_INLINE_VISIBILITY
839276792Sdimconstexpr
840276792Sdimbool
841276792Sdimoperator>=(const optional<_Tp>& __x, const _Tp& __v)
842276792Sdim{
843276792Sdim    return !(__x < __v);
844276792Sdim}
845276792Sdim
846276792Sdimtemplate <class _Tp>
847276792Sdiminline _LIBCPP_INLINE_VISIBILITY
848276792Sdimconstexpr
849276792Sdimbool
850276792Sdimoperator>=(const _Tp& __v, const optional<_Tp>& __x)
851276792Sdim{
852276792Sdim    return !(__v < __x);
853276792Sdim}
854276792Sdim
855276792Sdim
856276792Sdimtemplate <class _Tp>
857276792Sdiminline _LIBCPP_INLINE_VISIBILITY
858261272Sdimvoid
859261272Sdimswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
860261272Sdim{
861261272Sdim    __x.swap(__y);
862261272Sdim}
863261272Sdim
864261272Sdimtemplate <class _Tp>
865261272Sdiminline _LIBCPP_INLINE_VISIBILITY
866261272Sdimconstexpr
867261272Sdimoptional<typename decay<_Tp>::type>
868261272Sdimmake_optional(_Tp&& __v)
869261272Sdim{
870261272Sdim    return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
871261272Sdim}
872261272Sdim
873276792Sdim_LIBCPP_END_NAMESPACE_LFTS
874261272Sdim
875261272Sdim_LIBCPP_BEGIN_NAMESPACE_STD
876261272Sdim
877261272Sdimtemplate <class _Tp>
878261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
879261272Sdim{
880261272Sdim    typedef std::experimental::optional<_Tp> argument_type;
881261272Sdim    typedef size_t        result_type;
882261272Sdim
883261272Sdim    _LIBCPP_INLINE_VISIBILITY
884261272Sdim    result_type operator()(const argument_type& __opt) const _NOEXCEPT
885261272Sdim    {
886261272Sdim        return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
887261272Sdim    }
888261272Sdim};
889261272Sdim
890261272Sdim_LIBCPP_END_NAMESPACE_STD
891261272Sdim
892261272Sdim#endif  // _LIBCPP_STD_VER > 11
893261272Sdim
894276792Sdim#endif  // _LIBCPP_OPTIONAL
895