optional revision 261272
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
19261272Sdim#include <initializer_list>
20261272Sdim
21261272Sdimnamespace std { namespace experimental {
22261272Sdim
23261272Sdim// optional for object types
24261272Sdimtemplate <class T>
25261272Sdimclass optional
26261272Sdim{
27261272Sdimpublic:
28261272Sdim    typedef T value_type;
29261272Sdim
30261272Sdim    // constructors
31261272Sdim    constexpr optional() noexcept;
32261272Sdim    constexpr optional(nullopt_t) noexcept;
33261272Sdim    optional(const optional&);
34261272Sdim    optional(optional&&) noexcept(is_nothrow_move_constructible<T>::value);
35261272Sdim    constexpr optional(const T&);
36261272Sdim    constexpr optional(T&&);
37261272Sdim    template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
38261272Sdim    template <class U, class... Args>
39261272Sdim        constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
40261272Sdim
41261272Sdim    // destructor
42261272Sdim    ~optional();
43261272Sdim
44261272Sdim    // assignment
45261272Sdim    optional& operator=(nullopt_t) noexcept;
46261272Sdim    optional& operator=(const optional&);
47261272Sdim    optional& operator=(optional&&)
48261272Sdim        noexcept(is_nothrow_move_assignable<T>::value &&
49261272Sdim                 is_nothrow_move_constructible<T>::value);
50261272Sdim    template <class U> optional& operator=(U&&);
51261272Sdim    template <class... Args> void emplace(Args&&...);
52261272Sdim    template <class U, class... Args> void emplace(initializer_list<U>, Args&&...);
53261272Sdim
54261272Sdim    // swap
55261272Sdim    void swap(optional&)
56261272Sdim        noexcept(is_nothrow_move_constructible<T>::value &&
57261272Sdim                 noexcept(swap(declval<T&>(), declval<T&>())));
58261272Sdim
59261272Sdim    // observers
60261272Sdim    constexpr T const* operator->() const;
61261272Sdim    T* operator->();
62261272Sdim    constexpr T const& operator*() const;
63261272Sdim    T& operator*();
64261272Sdim    constexpr explicit operator bool() const noexcept;
65261272Sdim    constexpr T const& value() const;
66261272Sdim    T& value();
67261272Sdim    template <class U> constexpr T value_or(U&&) const&;
68261272Sdim    template <class U> T value_or(U&&) &&;
69261272Sdim};
70261272Sdim
71261272Sdim// In-place construction
72261272Sdimstruct in_place_t{};
73261272Sdimconstexpr in_place_t in_place{};
74261272Sdim
75261272Sdim// Disengaged state indicator
76261272Sdimstruct nullopt_t{see below};
77261272Sdimconstexpr nullopt_t nullopt(unspecified);
78261272Sdim
79261272Sdim// class bad_optional_access
80261272Sdimclass bad_optional_access
81261272Sdim    : public logic_error
82261272Sdim{
83261272Sdimpublic:
84261272Sdim    explicit bad_optional_access(const string& what_arg);
85261272Sdim    explicit bad_optional_access(const char* what_arg);
86261272Sdim};
87261272Sdim
88261272Sdim// Relational operators
89261272Sdimtemplate <class T> constexpr bool operator==(const optional<T>&, const optional<T>&);
90261272Sdimtemplate <class T> constexpr bool operator< (const optional<T>&, const optional<T>&);
91261272Sdim
92261272Sdim// Comparison with nullopt
93261272Sdimtemplate <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
94261272Sdimtemplate <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
95261272Sdimtemplate <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
96261272Sdimtemplate <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
97261272Sdim
98261272Sdim// Comparison with T
99261272Sdimtemplate <class T> constexpr bool operator==(const optional<T>&, const T&);
100261272Sdimtemplate <class T> constexpr bool operator==(const T&, const optional<T>&);
101261272Sdimtemplate <class T> constexpr bool operator<(const optional<T>&, const T&);
102261272Sdimtemplate <class T> constexpr bool operator<(const T&, const optional<T>&);
103261272Sdim
104261272Sdim// Specialized algorithms
105261272Sdimtemplate <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
106261272Sdimtemplate <class T> constexpr optional<typename decay<T>::type> make_optional(T&&);
107261272Sdim
108261272Sdim// hash support
109261272Sdimtemplate <class T> struct hash;
110261272Sdimtemplate <class T> struct hash<optional<T>>;
111261272Sdim
112261272Sdim}}  // std::experimental
113261272Sdim
114261272Sdim*/
115261272Sdim
116261272Sdim#include <__config>
117261272Sdim#include <functional>
118261272Sdim#include <stdexcept>
119261272Sdim
120261272Sdimnamespace std { namespace experimental {
121261272Sdim
122261272Sdimclass _LIBCPP_EXCEPTION_ABI bad_optional_access
123261272Sdim    : public logic_error
124261272Sdim{
125261272Sdimpublic:
126261272Sdim#if _LIBCPP_STD_VER > 11
127261272Sdim    _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const string& __arg)
128261272Sdim        : logic_error(__arg) {}
129261272Sdim    _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const char* __arg)
130261272Sdim        : logic_error(__arg) {}
131261272Sdim    _LIBCPP_INLINE_VISIBILITY bad_optional_access(const bad_optional_access&) noexcept = default;
132261272Sdim    _LIBCPP_INLINE_VISIBILITY bad_optional_access& operator=(const bad_optional_access&) noexcept = default;
133261272Sdim#else
134261272Sdimprivate:
135261272Sdim    bad_optional_access(const bad_optional_access&);
136261272Sdim    bad_optional_access& operator=(const bad_optional_access&);
137261272Sdimpublic:
138261272Sdim#endif  // _LIBCPP_STD_VER > 11
139261272Sdim    // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y
140261272Sdim    virtual ~bad_optional_access() _NOEXCEPT;
141261272Sdim};
142261272Sdim
143261272Sdim}}  // std::experimental
144261272Sdim
145261272Sdim#if _LIBCPP_STD_VER > 11
146261272Sdim
147261272Sdim#include <initializer_list>
148261272Sdim#include <type_traits>
149261272Sdim#include <new>
150261272Sdim#include <__functional_base>
151261272Sdim
152261272Sdim#include <__undef_min_max>
153261272Sdim
154261272Sdim#ifdef _LIBCPP_DEBUG
155261272Sdim#   include <__debug>
156261272Sdim#else
157261272Sdim#   define _LIBCPP_ASSERT(x, m) ((void)0)
158261272Sdim#endif
159261272Sdim
160261272Sdim#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
161261272Sdim#pragma GCC system_header
162261272Sdim#endif
163261272Sdim
164261272Sdimnamespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
165261272Sdim
166261272Sdimstruct in_place_t {};
167261272Sdimconstexpr in_place_t in_place{};
168261272Sdim
169261272Sdimstruct nullopt_t
170261272Sdim{
171261272Sdim    explicit constexpr nullopt_t(int) noexcept {}
172261272Sdim};
173261272Sdim
174261272Sdimconstexpr nullopt_t nullopt{0};
175261272Sdim
176261272Sdimtemplate <class _Tp, bool = is_trivially_destructible<_Tp>::value>
177261272Sdimclass __optional_storage
178261272Sdim{
179261272Sdimprotected:
180261272Sdim    typedef _Tp value_type;
181261272Sdim    union
182261272Sdim    {
183261272Sdim        char __null_state_;
184261272Sdim        value_type __val_;
185261272Sdim    };
186261272Sdim    bool __engaged_ = false;
187261272Sdim
188261272Sdim    _LIBCPP_INLINE_VISIBILITY
189261272Sdim    ~__optional_storage()
190261272Sdim    {
191261272Sdim        if (__engaged_)
192261272Sdim            __val_.~value_type();
193261272Sdim    }
194261272Sdim
195261272Sdim    _LIBCPP_INLINE_VISIBILITY
196261272Sdim    constexpr __optional_storage() noexcept
197261272Sdim        :  __null_state_('\0') {}
198261272Sdim
199261272Sdim    _LIBCPP_INLINE_VISIBILITY
200261272Sdim    __optional_storage(const __optional_storage& __x)
201261272Sdim        :  __engaged_(__x.__engaged_)
202261272Sdim        {
203261272Sdim            if (__engaged_)
204261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
205261272Sdim        }
206261272Sdim
207261272Sdim    _LIBCPP_INLINE_VISIBILITY
208261272Sdim    __optional_storage(__optional_storage&& __x)
209261272Sdim                      noexcept(is_nothrow_move_constructible<value_type>::value)
210261272Sdim        :  __engaged_(__x.__engaged_)
211261272Sdim        {
212261272Sdim            if (__engaged_)
213261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
214261272Sdim        }
215261272Sdim
216261272Sdim    _LIBCPP_INLINE_VISIBILITY
217261272Sdim    constexpr __optional_storage(const value_type& __v)
218261272Sdim        :  __val_(__v),
219261272Sdim           __engaged_(true) {}
220261272Sdim
221261272Sdim    _LIBCPP_INLINE_VISIBILITY
222261272Sdim    constexpr __optional_storage(value_type&& __v)
223261272Sdim        :  __val_(_VSTD::move(__v)),
224261272Sdim           __engaged_(true) {}
225261272Sdim
226261272Sdim    template <class... _Args>
227261272Sdim    _LIBCPP_INLINE_VISIBILITY
228261272Sdim    constexpr
229261272Sdim    explicit __optional_storage(in_place_t, _Args&&... __args)
230261272Sdim       :  __val_(_VSTD::forward<_Args>(__args)...),
231261272Sdim           __engaged_(true) {}
232261272Sdim};
233261272Sdim
234261272Sdimtemplate <class _Tp>
235261272Sdimclass __optional_storage<_Tp, true>
236261272Sdim{
237261272Sdimprotected:
238261272Sdim    typedef _Tp value_type;
239261272Sdim    union
240261272Sdim    {
241261272Sdim        char __null_state_;
242261272Sdim        value_type __val_;
243261272Sdim    };
244261272Sdim    bool __engaged_ = false;
245261272Sdim
246261272Sdim    _LIBCPP_INLINE_VISIBILITY
247261272Sdim    constexpr __optional_storage() noexcept
248261272Sdim        :  __null_state_('\0') {}
249261272Sdim
250261272Sdim    _LIBCPP_INLINE_VISIBILITY
251261272Sdim    __optional_storage(const __optional_storage& __x)
252261272Sdim        :  __engaged_(__x.__engaged_)
253261272Sdim        {
254261272Sdim            if (__engaged_)
255261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
256261272Sdim        }
257261272Sdim
258261272Sdim    _LIBCPP_INLINE_VISIBILITY
259261272Sdim    __optional_storage(__optional_storage&& __x)
260261272Sdim                      noexcept(is_nothrow_move_constructible<value_type>::value)
261261272Sdim        :  __engaged_(__x.__engaged_)
262261272Sdim        {
263261272Sdim            if (__engaged_)
264261272Sdim                ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
265261272Sdim        }
266261272Sdim
267261272Sdim    _LIBCPP_INLINE_VISIBILITY
268261272Sdim    constexpr __optional_storage(const value_type& __v)
269261272Sdim        :  __val_(__v),
270261272Sdim           __engaged_(true) {}
271261272Sdim
272261272Sdim    _LIBCPP_INLINE_VISIBILITY
273261272Sdim    constexpr __optional_storage(value_type&& __v)
274261272Sdim        :  __val_(_VSTD::move(__v)),
275261272Sdim           __engaged_(true) {}
276261272Sdim
277261272Sdim    template <class... _Args>
278261272Sdim    _LIBCPP_INLINE_VISIBILITY
279261272Sdim    constexpr
280261272Sdim    explicit __optional_storage(in_place_t, _Args&&... __args)
281261272Sdim       :  __val_(_VSTD::forward<_Args>(__args)...),
282261272Sdim           __engaged_(true) {}
283261272Sdim};
284261272Sdim
285261272Sdimtemplate <class _Tp>
286261272Sdimclass optional
287261272Sdim    : private __optional_storage<_Tp>
288261272Sdim{
289261272Sdim    typedef __optional_storage<_Tp> __base;
290261272Sdimpublic:
291261272Sdim    typedef _Tp value_type;
292261272Sdim
293261272Sdim    static_assert(!is_reference<value_type>::value,
294261272Sdim              "Instantiation of optional with a reference type is ill-formed.");
295261272Sdim    static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
296261272Sdim              "Instantiation of optional with a in_place_t type is ill-formed.");
297261272Sdim    static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
298261272Sdim              "Instantiation of optional with a nullopt_t type is ill-formed.");
299261272Sdim    static_assert(is_object<value_type>::value,
300261272Sdim        "Instantiation of optional with a non-object type is undefined behavior.");
301261272Sdim    static_assert(is_nothrow_destructible<value_type>::value,
302261272Sdim        "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
303261272Sdim
304261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
305261272Sdim    _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
306261272Sdim    _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
307261272Sdim    _LIBCPP_INLINE_VISIBILITY ~optional() = default;
308261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
309261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
310261272Sdim        : __base(__v) {}
311261272Sdim    _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
312261272Sdim        : __base(_VSTD::move(__v)) {}
313261272Sdim
314261272Sdim    template <class... _Args,
315261272Sdim              class = typename enable_if
316261272Sdim                      <
317261272Sdim                           is_constructible<value_type, _Args...>::value
318261272Sdim                      >::type
319261272Sdim             >
320261272Sdim    _LIBCPP_INLINE_VISIBILITY
321261272Sdim    constexpr
322261272Sdim    explicit optional(in_place_t, _Args&&... __args)
323261272Sdim        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
324261272Sdim
325261272Sdim    template <class _Up, class... _Args,
326261272Sdim              class = typename enable_if
327261272Sdim                      <
328261272Sdim                           is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
329261272Sdim                      >::type
330261272Sdim             >
331261272Sdim    _LIBCPP_INLINE_VISIBILITY
332261272Sdim    constexpr
333261272Sdim    explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
334261272Sdim        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
335261272Sdim
336261272Sdim    _LIBCPP_INLINE_VISIBILITY
337261272Sdim    optional& operator=(nullopt_t) noexcept
338261272Sdim    {
339261272Sdim        if (this->__engaged_)
340261272Sdim        {
341261272Sdim            this->__val_.~value_type();
342261272Sdim            this->__engaged_ = false;
343261272Sdim        }
344261272Sdim        return *this;
345261272Sdim    }
346261272Sdim
347261272Sdim    _LIBCPP_INLINE_VISIBILITY
348261272Sdim    optional&
349261272Sdim    operator=(const optional& __opt)
350261272Sdim    {
351261272Sdim        if (this->__engaged_ == __opt.__engaged_)
352261272Sdim        {
353261272Sdim            if (this->__engaged_)
354261272Sdim                this->__val_ = __opt.__val_;
355261272Sdim        }
356261272Sdim        else
357261272Sdim        {
358261272Sdim            if (this->__engaged_)
359261272Sdim                this->__val_.~value_type();
360261272Sdim            else
361261272Sdim                ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
362261272Sdim            this->__engaged_ = __opt.__engaged_;
363261272Sdim        }
364261272Sdim        return *this;
365261272Sdim    }
366261272Sdim
367261272Sdim    _LIBCPP_INLINE_VISIBILITY
368261272Sdim    optional&
369261272Sdim    operator=(optional&& __opt)
370261272Sdim        noexcept(is_nothrow_move_assignable<value_type>::value &&
371261272Sdim                 is_nothrow_move_constructible<value_type>::value)
372261272Sdim    {
373261272Sdim        if (this->__engaged_ == __opt.__engaged_)
374261272Sdim        {
375261272Sdim            if (this->__engaged_)
376261272Sdim                this->__val_ = _VSTD::move(__opt.__val_);
377261272Sdim        }
378261272Sdim        else
379261272Sdim        {
380261272Sdim            if (this->__engaged_)
381261272Sdim                this->__val_.~value_type();
382261272Sdim            else
383261272Sdim                ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
384261272Sdim            this->__engaged_ = __opt.__engaged_;
385261272Sdim        }
386261272Sdim        return *this;
387261272Sdim    }
388261272Sdim
389261272Sdim    template <class _Up,
390261272Sdim              class = typename enable_if
391261272Sdim                      <
392261272Sdim                          is_same<typename remove_reference<_Up>::type, value_type>::value &&
393261272Sdim                          is_constructible<value_type, _Up>::value &&
394261272Sdim                          is_assignable<value_type&, _Up>::value
395261272Sdim                      >::type
396261272Sdim             >
397261272Sdim    _LIBCPP_INLINE_VISIBILITY
398261272Sdim    optional&
399261272Sdim    operator=(_Up&& __v)
400261272Sdim    {
401261272Sdim        if (this->__engaged_)
402261272Sdim            this->__val_ = _VSTD::forward<_Up>(__v);
403261272Sdim        else
404261272Sdim        {
405261272Sdim            ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
406261272Sdim            this->__engaged_ = true;
407261272Sdim        }
408261272Sdim        return *this;
409261272Sdim    }
410261272Sdim
411261272Sdim    template <class... _Args,
412261272Sdim              class = typename enable_if
413261272Sdim                      <
414261272Sdim                          is_constructible<value_type, _Args...>::value
415261272Sdim                      >::type
416261272Sdim             >
417261272Sdim    _LIBCPP_INLINE_VISIBILITY
418261272Sdim    void
419261272Sdim    emplace(_Args&&... __args)
420261272Sdim    {
421261272Sdim        *this = nullopt;
422261272Sdim        ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
423261272Sdim        this->__engaged_ = true;
424261272Sdim    }
425261272Sdim
426261272Sdim    template <class _Up, class... _Args,
427261272Sdim              class = typename enable_if
428261272Sdim                      <
429261272Sdim                          is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
430261272Sdim                      >::type
431261272Sdim             >
432261272Sdim    _LIBCPP_INLINE_VISIBILITY
433261272Sdim    void
434261272Sdim    emplace(initializer_list<_Up> __il, _Args&&... __args)
435261272Sdim    {
436261272Sdim        *this = nullopt;
437261272Sdim        ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
438261272Sdim        this->__engaged_ = true;
439261272Sdim    }
440261272Sdim
441261272Sdim    _LIBCPP_INLINE_VISIBILITY
442261272Sdim    void
443261272Sdim    swap(optional& __opt)
444261272Sdim        noexcept(is_nothrow_move_constructible<value_type>::value &&
445261272Sdim                 __is_nothrow_swappable<value_type>::value)
446261272Sdim    {
447261272Sdim        using _VSTD::swap;
448261272Sdim        if (this->__engaged_ == __opt.__engaged_)
449261272Sdim        {
450261272Sdim            if (this->__engaged_)
451261272Sdim                swap(this->__val_, __opt.__val_);
452261272Sdim        }
453261272Sdim        else
454261272Sdim        {
455261272Sdim            if (this->__engaged_)
456261272Sdim            {
457261272Sdim                ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
458261272Sdim                this->__val_.~value_type();
459261272Sdim            }
460261272Sdim            else
461261272Sdim            {
462261272Sdim                ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
463261272Sdim                __opt.__val_.~value_type();
464261272Sdim            }
465261272Sdim            swap(this->__engaged_, __opt.__engaged_);
466261272Sdim        }
467261272Sdim    }
468261272Sdim
469261272Sdim    _LIBCPP_INLINE_VISIBILITY
470261272Sdim    constexpr
471261272Sdim    value_type const*
472261272Sdim    operator->() const
473261272Sdim    {
474261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
475261272Sdim        return __operator_arrow(__has_operator_addressof<value_type>{});
476261272Sdim    }
477261272Sdim
478261272Sdim    _LIBCPP_INLINE_VISIBILITY
479261272Sdim    value_type*
480261272Sdim    operator->()
481261272Sdim    {
482261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
483261272Sdim        return _VSTD::addressof(this->__val_);
484261272Sdim    }
485261272Sdim
486261272Sdim    _LIBCPP_INLINE_VISIBILITY
487261272Sdim    constexpr
488261272Sdim    const value_type&
489261272Sdim    operator*() const
490261272Sdim    {
491261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
492261272Sdim        return this->__val_;
493261272Sdim    }
494261272Sdim
495261272Sdim    _LIBCPP_INLINE_VISIBILITY
496261272Sdim    value_type&
497261272Sdim    operator*()
498261272Sdim    {
499261272Sdim        _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
500261272Sdim        return this->__val_;
501261272Sdim    }
502261272Sdim
503261272Sdim    _LIBCPP_INLINE_VISIBILITY
504261272Sdim    constexpr explicit operator bool() const noexcept {return this->__engaged_;}
505261272Sdim
506261272Sdim    _LIBCPP_INLINE_VISIBILITY
507261272Sdim    constexpr value_type const& value() const
508261272Sdim    {
509261272Sdim        if (!this->__engaged_)
510261272Sdim            throw bad_optional_access("optional<T>::value: not engaged");
511261272Sdim        return this->__val_;
512261272Sdim    }
513261272Sdim
514261272Sdim    _LIBCPP_INLINE_VISIBILITY
515261272Sdim    value_type& value()
516261272Sdim    {
517261272Sdim        if (!this->__engaged_)
518261272Sdim            throw bad_optional_access("optional<T>::value: not engaged");
519261272Sdim        return this->__val_;
520261272Sdim    }
521261272Sdim
522261272Sdim    template <class _Up>
523261272Sdim    _LIBCPP_INLINE_VISIBILITY
524261272Sdim    constexpr value_type value_or(_Up&& __v) const&
525261272Sdim    {
526261272Sdim        static_assert(is_copy_constructible<value_type>::value,
527261272Sdim                      "optional<T>::value_or: T must be copy constructible");
528261272Sdim        static_assert(is_convertible<_Up, value_type>::value,
529261272Sdim                      "optional<T>::value_or: U must be convertible to T");
530261272Sdim        return this->__engaged_ ? this->__val_ :
531261272Sdim                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
532261272Sdim    }
533261272Sdim
534261272Sdim    template <class _Up>
535261272Sdim    _LIBCPP_INLINE_VISIBILITY
536261272Sdim    value_type value_or(_Up&& __v) &&
537261272Sdim    {
538261272Sdim        static_assert(is_move_constructible<value_type>::value,
539261272Sdim                      "optional<T>::value_or: T must be move constructible");
540261272Sdim        static_assert(is_convertible<_Up, value_type>::value,
541261272Sdim                      "optional<T>::value_or: U must be convertible to T");
542261272Sdim        return this->__engaged_ ? _VSTD::move(this->__val_) :
543261272Sdim                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
544261272Sdim    }
545261272Sdim
546261272Sdimprivate:
547261272Sdim    _LIBCPP_INLINE_VISIBILITY
548261272Sdim    value_type const*
549261272Sdim    __operator_arrow(true_type) const
550261272Sdim    {
551261272Sdim        return _VSTD::addressof(this->__val_);
552261272Sdim    }
553261272Sdim
554261272Sdim    _LIBCPP_INLINE_VISIBILITY
555261272Sdim    constexpr
556261272Sdim    value_type const*
557261272Sdim    __operator_arrow(false_type) const
558261272Sdim    {
559261272Sdim        return &this->__val_;
560261272Sdim    }
561261272Sdim};
562261272Sdim
563261272Sdimtemplate <class _Tp>
564261272Sdiminline _LIBCPP_INLINE_VISIBILITY
565261272Sdimconstexpr
566261272Sdimbool
567261272Sdimoperator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
568261272Sdim{
569261272Sdim    if (static_cast<bool>(__x) != static_cast<bool>(__y))
570261272Sdim        return false;
571261272Sdim    if (!static_cast<bool>(__x))
572261272Sdim        return true;
573261272Sdim    return *__x == *__y;
574261272Sdim}
575261272Sdim
576261272Sdimtemplate <class _Tp>
577261272Sdiminline _LIBCPP_INLINE_VISIBILITY
578261272Sdimconstexpr
579261272Sdimbool
580261272Sdimoperator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
581261272Sdim{
582261272Sdim    if (!static_cast<bool>(__y))
583261272Sdim        return false;
584261272Sdim    if (!static_cast<bool>(__x))
585261272Sdim        return true;
586261272Sdim    return less<_Tp>{}(*__x, *__y);
587261272Sdim}
588261272Sdim
589261272Sdimtemplate <class _Tp>
590261272Sdiminline _LIBCPP_INLINE_VISIBILITY
591261272Sdimconstexpr
592261272Sdimbool
593261272Sdimoperator==(const optional<_Tp>& __x, nullopt_t) noexcept
594261272Sdim{
595261272Sdim    return !static_cast<bool>(__x);
596261272Sdim}
597261272Sdim
598261272Sdimtemplate <class _Tp>
599261272Sdiminline _LIBCPP_INLINE_VISIBILITY
600261272Sdimconstexpr
601261272Sdimbool
602261272Sdimoperator==(nullopt_t, const optional<_Tp>& __x) noexcept
603261272Sdim{
604261272Sdim    return !static_cast<bool>(__x);
605261272Sdim}
606261272Sdim
607261272Sdimtemplate <class _Tp>
608261272Sdiminline _LIBCPP_INLINE_VISIBILITY
609261272Sdimconstexpr
610261272Sdimbool
611261272Sdimoperator<(const optional<_Tp>&, nullopt_t) noexcept
612261272Sdim{
613261272Sdim    return false;
614261272Sdim}
615261272Sdim
616261272Sdimtemplate <class _Tp>
617261272Sdiminline _LIBCPP_INLINE_VISIBILITY
618261272Sdimconstexpr
619261272Sdimbool
620261272Sdimoperator<(nullopt_t, const optional<_Tp>& __x) noexcept
621261272Sdim{
622261272Sdim    return static_cast<bool>(__x);
623261272Sdim}
624261272Sdim
625261272Sdimtemplate <class _Tp>
626261272Sdiminline _LIBCPP_INLINE_VISIBILITY
627261272Sdimconstexpr
628261272Sdimbool
629261272Sdimoperator==(const optional<_Tp>& __x, const _Tp& __v)
630261272Sdim{
631261272Sdim    return static_cast<bool>(__x) ? *__x == __v : false;
632261272Sdim}
633261272Sdim
634261272Sdimtemplate <class _Tp>
635261272Sdiminline _LIBCPP_INLINE_VISIBILITY
636261272Sdimconstexpr
637261272Sdimbool
638261272Sdimoperator==(const _Tp& __v, const optional<_Tp>& __x)
639261272Sdim{
640261272Sdim    return static_cast<bool>(__x) ? *__x == __v : false;
641261272Sdim}
642261272Sdim
643261272Sdimtemplate <class _Tp>
644261272Sdiminline _LIBCPP_INLINE_VISIBILITY
645261272Sdimconstexpr
646261272Sdimbool
647261272Sdimoperator<(const optional<_Tp>& __x, const _Tp& __v)
648261272Sdim{
649261272Sdim    return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
650261272Sdim}
651261272Sdim
652261272Sdimtemplate <class _Tp>
653261272Sdiminline _LIBCPP_INLINE_VISIBILITY
654261272Sdimconstexpr
655261272Sdimbool
656261272Sdimoperator<(const _Tp& __v, const optional<_Tp>& __x)
657261272Sdim{
658261272Sdim    return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
659261272Sdim}
660261272Sdim
661261272Sdimtemplate <class _Tp>
662261272Sdiminline _LIBCPP_INLINE_VISIBILITY
663261272Sdimvoid
664261272Sdimswap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
665261272Sdim{
666261272Sdim    __x.swap(__y);
667261272Sdim}
668261272Sdim
669261272Sdimtemplate <class _Tp>
670261272Sdiminline _LIBCPP_INLINE_VISIBILITY
671261272Sdimconstexpr
672261272Sdimoptional<typename decay<_Tp>::type>
673261272Sdimmake_optional(_Tp&& __v)
674261272Sdim{
675261272Sdim    return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
676261272Sdim}
677261272Sdim
678261272Sdim}}}  // namespace std::experimental::__library_fundamentals_v1
679261272Sdim
680261272Sdim_LIBCPP_BEGIN_NAMESPACE_STD
681261272Sdim
682261272Sdimtemplate <class _Tp>
683261272Sdimstruct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
684261272Sdim{
685261272Sdim    typedef std::experimental::optional<_Tp> argument_type;
686261272Sdim    typedef size_t        result_type;
687261272Sdim
688261272Sdim    _LIBCPP_INLINE_VISIBILITY
689261272Sdim    result_type operator()(const argument_type& __opt) const _NOEXCEPT
690261272Sdim    {
691261272Sdim        return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
692261272Sdim    }
693261272Sdim};
694261272Sdim
695261272Sdim_LIBCPP_END_NAMESPACE_STD
696261272Sdim
697261272Sdim#endif  // _LIBCPP_STD_VER > 11
698261272Sdim
699261272Sdim#endif  // _LIBCPP_ARRAY
700