Home | History | Annotate | Download | only in experimental
      1 // -*- C++ -*-
      2 //===-------------------------- optional ----------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_OPTIONAL
     12 #define _LIBCPP_OPTIONAL
     13 
     14 /*
     15     optional synopsis
     16 
     17 // C++1y
     18 
     19 namespace std { namespace experimental { inline namespace fundamentals_v1 {
     20 
     21     // 5.3, optional for object types
     22     template <class T> class optional;
     23 
     24     // 5.4, In-place construction
     25     struct in_place_t{};
     26     constexpr in_place_t in_place{};
     27 
     28     // 5.5, No-value state indicator
     29     struct nullopt_t{see below};
     30     constexpr nullopt_t nullopt(unspecified);
     31 
     32     // 5.6, Class bad_optional_access
     33     class bad_optional_access;
     34 
     35     // 5.7, Relational operators
     36     template <class T>
     37       constexpr bool operator==(const optional<T>&, const optional<T>&);
     38     template <class T>
     39       constexpr bool operator!=(const optional<T>&, const optional<T>&);
     40     template <class T>
     41       constexpr bool operator<(const optional<T>&, const optional<T>&);
     42     template <class T>
     43       constexpr bool operator>(const optional<T>&, const optional<T>&);
     44     template <class T>
     45       constexpr bool operator<=(const optional<T>&, const optional<T>&);
     46     template <class T>
     47       constexpr bool operator>=(const optional<T>&, const optional<T>&);
     48 
     49     // 5.8, Comparison with nullopt
     50     template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
     51     template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
     52     template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
     53     template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
     54     template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
     55     template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
     56     template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
     57     template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
     58     template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
     59     template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
     60     template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
     61     template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
     62 
     63     // 5.9, Comparison with T
     64     template <class T> constexpr bool operator==(const optional<T>&, const T&);
     65     template <class T> constexpr bool operator==(const T&, const optional<T>&);
     66     template <class T> constexpr bool operator!=(const optional<T>&, const T&);
     67     template <class T> constexpr bool operator!=(const T&, const optional<T>&);
     68     template <class T> constexpr bool operator<(const optional<T>&, const T&);
     69     template <class T> constexpr bool operator<(const T&, const optional<T>&);
     70     template <class T> constexpr bool operator<=(const optional<T>&, const T&);
     71     template <class T> constexpr bool operator<=(const T&, const optional<T>&);
     72     template <class T> constexpr bool operator>(const optional<T>&, const T&);
     73     template <class T> constexpr bool operator>(const T&, const optional<T>&);
     74     template <class T> constexpr bool operator>=(const optional<T>&, const T&);
     75     template <class T> constexpr bool operator>=(const T&, const optional<T>&);
     76 
     77     // 5.10, Specialized algorithms
     78     template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
     79     template <class T> constexpr optional<see below> make_optional(T&&);
     80 
     81 	template <class T>
     82 	class optional
     83 	{
     84 	public:
     85 	  typedef T value_type;
     86 
     87 	  // 5.3.1, Constructors
     88 	  constexpr optional() noexcept;
     89 	  constexpr optional(nullopt_t) noexcept;
     90 	  optional(const optional&);
     91 	  optional(optional&&) noexcept(see below);
     92 	  constexpr optional(const T&);
     93 	  constexpr optional(T&&);
     94 	  template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
     95 	  template <class U, class... Args>
     96 		constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
     97 
     98 	  // 5.3.2, Destructor
     99 	  ~optional();
    100 
    101 	  // 5.3.3, Assignment
    102 	  optional& operator=(nullopt_t) noexcept;
    103 	  optional& operator=(const optional&);
    104 	  optional& operator=(optional&&) noexcept(see below);
    105 	  template <class U> optional& operator=(U&&);
    106 	  template <class... Args> void emplace(Args&&...);
    107 	  template <class U, class... Args>
    108 		void emplace(initializer_list<U>, Args&&...);
    109 
    110 	  // 5.3.4, Swap
    111 	  void swap(optional&) noexcept(see below);
    112 
    113 	  // 5.3.5, Observers
    114 	  constexpr T const* operator ->() const;
    115 	  constexpr T* operator ->();
    116 	  constexpr T const& operator *() const &;
    117 	  constexpr T& operator *() &;
    118 	  constexpr T&& operator *() &&;
    119 	  constexpr const T&& operator *() const &&;
    120 	  constexpr explicit operator bool() const noexcept;
    121 	  constexpr T const& value() const &;
    122 	  constexpr T& value() &;
    123 	  constexpr T&& value() &&;
    124 	  constexpr const T&& value() const &&;
    125 	  template <class U> constexpr T value_or(U&&) const &;
    126 	  template <class U> constexpr T value_or(U&&) &&;
    127 
    128 	private:
    129 	  T*   val;  // exposition only
    130 	};
    131 
    132   } // namespace fundamentals_v1
    133   } // namespace experimental
    134 
    135   // 5.11, Hash support
    136   template <class T> struct hash;
    137   template <class T> struct hash<experimental::optional<T>>;
    138 
    139 } // namespace std
    140 
    141 */
    142 
    143 #include <experimental/__config>
    144 #include <functional>
    145 #include <stdexcept>
    146 
    147 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
    148 class _LIBCPP_EXCEPTION_ABI bad_optional_access
    149     : public std::logic_error
    150 {
    151 public:
    152 	bad_optional_access() : std::logic_error("Bad optional Access") {}
    153 
    154 //	Get the key function ~bad_optional_access() into the dylib
    155     virtual ~bad_optional_access() _NOEXCEPT;
    156 };
    157 
    158 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
    159 
    160 
    161 #if _LIBCPP_STD_VER > 11
    162 
    163 #include <initializer_list>
    164 #include <type_traits>
    165 #include <new>
    166 #include <__functional_base>
    167 #include <__undef_min_max>
    168 #include <__debug>
    169 
    170 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    171 #pragma GCC system_header
    172 #endif
    173 
    174 _LIBCPP_BEGIN_NAMESPACE_LFTS
    175 
    176 struct in_place_t {};
    177 constexpr in_place_t in_place{};
    178 
    179 struct nullopt_t
    180 {
    181     explicit constexpr nullopt_t(int) noexcept {}
    182 };
    183 
    184 constexpr nullopt_t nullopt{0};
    185 
    186 template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
    187 class __optional_storage
    188 {
    189 protected:
    190     typedef _Tp value_type;
    191     union
    192     {
    193         char __null_state_;
    194         value_type __val_;
    195     };
    196     bool __engaged_ = false;
    197 
    198     _LIBCPP_INLINE_VISIBILITY
    199     ~__optional_storage()
    200     {
    201         if (__engaged_)
    202             __val_.~value_type();
    203     }
    204 
    205     _LIBCPP_INLINE_VISIBILITY
    206     constexpr __optional_storage() noexcept
    207         :  __null_state_('\0') {}
    208 
    209     _LIBCPP_INLINE_VISIBILITY
    210     __optional_storage(const __optional_storage& __x)
    211         :  __engaged_(__x.__engaged_)
    212         {
    213             if (__engaged_)
    214                 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
    215         }
    216 
    217     _LIBCPP_INLINE_VISIBILITY
    218     __optional_storage(__optional_storage&& __x)
    219                       noexcept(is_nothrow_move_constructible<value_type>::value)
    220         :  __engaged_(__x.__engaged_)
    221         {
    222             if (__engaged_)
    223                 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
    224         }
    225 
    226     _LIBCPP_INLINE_VISIBILITY
    227     constexpr __optional_storage(const value_type& __v)
    228         :  __val_(__v),
    229            __engaged_(true) {}
    230 
    231     _LIBCPP_INLINE_VISIBILITY
    232     constexpr __optional_storage(value_type&& __v)
    233         :  __val_(_VSTD::move(__v)),
    234            __engaged_(true) {}
    235 
    236     template <class... _Args>
    237     _LIBCPP_INLINE_VISIBILITY
    238     constexpr
    239     explicit __optional_storage(in_place_t, _Args&&... __args)
    240        :  __val_(_VSTD::forward<_Args>(__args)...),
    241            __engaged_(true) {}
    242 };
    243 
    244 template <class _Tp>
    245 class __optional_storage<_Tp, true>
    246 {
    247 protected:
    248     typedef _Tp value_type;
    249     union
    250     {
    251         char __null_state_;
    252         value_type __val_;
    253     };
    254     bool __engaged_ = false;
    255 
    256     _LIBCPP_INLINE_VISIBILITY
    257     constexpr __optional_storage() noexcept
    258         :  __null_state_('\0') {}
    259 
    260     _LIBCPP_INLINE_VISIBILITY
    261     __optional_storage(const __optional_storage& __x)
    262         :  __engaged_(__x.__engaged_)
    263         {
    264             if (__engaged_)
    265                 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
    266         }
    267 
    268     _LIBCPP_INLINE_VISIBILITY
    269     __optional_storage(__optional_storage&& __x)
    270                       noexcept(is_nothrow_move_constructible<value_type>::value)
    271         :  __engaged_(__x.__engaged_)
    272         {
    273             if (__engaged_)
    274                 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
    275         }
    276 
    277     _LIBCPP_INLINE_VISIBILITY
    278     constexpr __optional_storage(const value_type& __v)
    279         :  __val_(__v),
    280            __engaged_(true) {}
    281 
    282     _LIBCPP_INLINE_VISIBILITY
    283     constexpr __optional_storage(value_type&& __v)
    284         :  __val_(_VSTD::move(__v)),
    285            __engaged_(true) {}
    286 
    287     template <class... _Args>
    288     _LIBCPP_INLINE_VISIBILITY
    289     constexpr
    290     explicit __optional_storage(in_place_t, _Args&&... __args)
    291        :  __val_(_VSTD::forward<_Args>(__args)...),
    292            __engaged_(true) {}
    293 };
    294 
    295 template <class _Tp>
    296 class optional
    297     : private __optional_storage<_Tp>
    298 {
    299     typedef __optional_storage<_Tp> __base;
    300 public:
    301     typedef _Tp value_type;
    302 
    303     static_assert(!is_reference<value_type>::value,
    304               "Instantiation of optional with a reference type is ill-formed.");
    305     static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
    306               "Instantiation of optional with a in_place_t type is ill-formed.");
    307     static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
    308               "Instantiation of optional with a nullopt_t type is ill-formed.");
    309     static_assert(is_object<value_type>::value,
    310         "Instantiation of optional with a non-object type is undefined behavior.");
    311     static_assert(is_nothrow_destructible<value_type>::value,
    312         "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
    313 
    314     _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
    315     _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
    316     _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
    317     _LIBCPP_INLINE_VISIBILITY ~optional() = default;
    318     _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
    319     _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
    320         : __base(__v) {}
    321     _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
    322         : __base(_VSTD::move(__v)) {}
    323 
    324     template <class... _Args,
    325               class = typename enable_if
    326                       <
    327                            is_constructible<value_type, _Args...>::value
    328                       >::type
    329              >
    330     _LIBCPP_INLINE_VISIBILITY
    331     constexpr
    332     explicit optional(in_place_t, _Args&&... __args)
    333         : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
    334 
    335     template <class _Up, class... _Args,
    336               class = typename enable_if
    337                       <
    338                            is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    339                       >::type
    340              >
    341     _LIBCPP_INLINE_VISIBILITY
    342     constexpr
    343     explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
    344         : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
    345 
    346     _LIBCPP_INLINE_VISIBILITY
    347     optional& operator=(nullopt_t) noexcept
    348     {
    349         if (this->__engaged_)
    350         {
    351             this->__val_.~value_type();
    352             this->__engaged_ = false;
    353         }
    354         return *this;
    355     }
    356 
    357     _LIBCPP_INLINE_VISIBILITY
    358     optional&
    359     operator=(const optional& __opt)
    360     {
    361         if (this->__engaged_ == __opt.__engaged_)
    362         {
    363             if (this->__engaged_)
    364                 this->__val_ = __opt.__val_;
    365         }
    366         else
    367         {
    368             if (this->__engaged_)
    369                 this->__val_.~value_type();
    370             else
    371                 ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
    372             this->__engaged_ = __opt.__engaged_;
    373         }
    374         return *this;
    375     }
    376 
    377     _LIBCPP_INLINE_VISIBILITY
    378     optional&
    379     operator=(optional&& __opt)
    380         noexcept(is_nothrow_move_assignable<value_type>::value &&
    381                  is_nothrow_move_constructible<value_type>::value)
    382     {
    383         if (this->__engaged_ == __opt.__engaged_)
    384         {
    385             if (this->__engaged_)
    386                 this->__val_ = _VSTD::move(__opt.__val_);
    387         }
    388         else
    389         {
    390             if (this->__engaged_)
    391                 this->__val_.~value_type();
    392             else
    393                 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
    394             this->__engaged_ = __opt.__engaged_;
    395         }
    396         return *this;
    397     }
    398 
    399     template <class _Up,
    400               class = typename enable_if
    401                       <
    402                           is_same<typename remove_reference<_Up>::type, value_type>::value &&
    403                           is_constructible<value_type, _Up>::value &&
    404                           is_assignable<value_type&, _Up>::value
    405                       >::type
    406              >
    407     _LIBCPP_INLINE_VISIBILITY
    408     optional&
    409     operator=(_Up&& __v)
    410     {
    411         if (this->__engaged_)
    412             this->__val_ = _VSTD::forward<_Up>(__v);
    413         else
    414         {
    415             ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
    416             this->__engaged_ = true;
    417         }
    418         return *this;
    419     }
    420 
    421     template <class... _Args,
    422               class = typename enable_if
    423                       <
    424                           is_constructible<value_type, _Args...>::value
    425                       >::type
    426              >
    427     _LIBCPP_INLINE_VISIBILITY
    428     void
    429     emplace(_Args&&... __args)
    430     {
    431         *this = nullopt;
    432         ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
    433         this->__engaged_ = true;
    434     }
    435 
    436     template <class _Up, class... _Args,
    437               class = typename enable_if
    438                       <
    439                           is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    440                       >::type
    441              >
    442     _LIBCPP_INLINE_VISIBILITY
    443     void
    444     emplace(initializer_list<_Up> __il, _Args&&... __args)
    445     {
    446         *this = nullopt;
    447         ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
    448         this->__engaged_ = true;
    449     }
    450 
    451     _LIBCPP_INLINE_VISIBILITY
    452     void
    453     swap(optional& __opt)
    454         noexcept(is_nothrow_move_constructible<value_type>::value &&
    455                  __is_nothrow_swappable<value_type>::value)
    456     {
    457         using _VSTD::swap;
    458         if (this->__engaged_ == __opt.__engaged_)
    459         {
    460             if (this->__engaged_)
    461                 swap(this->__val_, __opt.__val_);
    462         }
    463         else
    464         {
    465             if (this->__engaged_)
    466             {
    467                 ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
    468                 this->__val_.~value_type();
    469             }
    470             else
    471             {
    472                 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
    473                 __opt.__val_.~value_type();
    474             }
    475             swap(this->__engaged_, __opt.__engaged_);
    476         }
    477     }
    478 
    479     _LIBCPP_INLINE_VISIBILITY
    480     constexpr
    481     value_type const*
    482     operator->() const
    483     {
    484         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    485         return __operator_arrow(__has_operator_addressof<value_type>{});
    486     }
    487 
    488     _LIBCPP_INLINE_VISIBILITY
    489     value_type*
    490     operator->()
    491     {
    492         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    493         return _VSTD::addressof(this->__val_);
    494     }
    495 
    496     _LIBCPP_INLINE_VISIBILITY
    497     constexpr
    498     const value_type&
    499     operator*() const
    500     {
    501         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    502         return this->__val_;
    503     }
    504 
    505     _LIBCPP_INLINE_VISIBILITY
    506     value_type&
    507     operator*()
    508     {
    509         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    510         return this->__val_;
    511     }
    512 
    513     _LIBCPP_INLINE_VISIBILITY
    514     constexpr explicit operator bool() const noexcept {return this->__engaged_;}
    515 
    516     _LIBCPP_INLINE_VISIBILITY
    517     constexpr value_type const& value() const
    518     {
    519         if (!this->__engaged_)
    520             throw bad_optional_access();
    521         return this->__val_;
    522     }
    523 
    524     _LIBCPP_INLINE_VISIBILITY
    525     value_type& value()
    526     {
    527         if (!this->__engaged_)
    528             throw bad_optional_access();
    529         return this->__val_;
    530     }
    531 
    532     template <class _Up>
    533     _LIBCPP_INLINE_VISIBILITY
    534     constexpr value_type value_or(_Up&& __v) const&
    535     {
    536         static_assert(is_copy_constructible<value_type>::value,
    537                       "optional<T>::value_or: T must be copy constructible");
    538         static_assert(is_convertible<_Up, value_type>::value,
    539                       "optional<T>::value_or: U must be convertible to T");
    540         return this->__engaged_ ? this->__val_ :
    541                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    542     }
    543 
    544     template <class _Up>
    545     _LIBCPP_INLINE_VISIBILITY
    546     value_type value_or(_Up&& __v) &&
    547     {
    548         static_assert(is_move_constructible<value_type>::value,
    549                       "optional<T>::value_or: T must be move constructible");
    550         static_assert(is_convertible<_Up, value_type>::value,
    551                       "optional<T>::value_or: U must be convertible to T");
    552         return this->__engaged_ ? _VSTD::move(this->__val_) :
    553                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    554     }
    555 
    556 private:
    557     _LIBCPP_INLINE_VISIBILITY
    558     value_type const*
    559     __operator_arrow(true_type) const
    560     {
    561         return _VSTD::addressof(this->__val_);
    562     }
    563 
    564     _LIBCPP_INLINE_VISIBILITY
    565     constexpr
    566     value_type const*
    567     __operator_arrow(false_type) const
    568     {
    569         return &this->__val_;
    570     }
    571 };
    572 
    573 // Comparisons between optionals
    574 template <class _Tp>
    575 inline _LIBCPP_INLINE_VISIBILITY
    576 constexpr
    577 bool
    578 operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
    579 {
    580     if (static_cast<bool>(__x) != static_cast<bool>(__y))
    581         return false;
    582     if (!static_cast<bool>(__x))
    583         return true;
    584     return *__x == *__y;
    585 }
    586 
    587 template <class _Tp>
    588 inline _LIBCPP_INLINE_VISIBILITY
    589 constexpr
    590 bool
    591 operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    592 {
    593     return !(__x == __y);
    594 }
    595 
    596 template <class _Tp>
    597 inline _LIBCPP_INLINE_VISIBILITY
    598 constexpr
    599 bool
    600 operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
    601 {
    602     if (!static_cast<bool>(__y))
    603         return false;
    604     if (!static_cast<bool>(__x))
    605         return true;
    606     return *__x < *__y;
    607 }
    608 
    609 template <class _Tp>
    610 inline _LIBCPP_INLINE_VISIBILITY
    611 constexpr
    612 bool
    613 operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
    614 {
    615     return __y < __x;
    616 }
    617 
    618 template <class _Tp>
    619 inline _LIBCPP_INLINE_VISIBILITY
    620 constexpr
    621 bool
    622 operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    623 {
    624     return !(__y < __x);
    625 }
    626 
    627 template <class _Tp>
    628 inline _LIBCPP_INLINE_VISIBILITY
    629 constexpr
    630 bool
    631 operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    632 {
    633     return !(__x < __y);
    634 }
    635 
    636 
    637 // Comparisons with nullopt
    638 template <class _Tp>
    639 inline _LIBCPP_INLINE_VISIBILITY
    640 constexpr
    641 bool
    642 operator==(const optional<_Tp>& __x, nullopt_t) noexcept
    643 {
    644     return !static_cast<bool>(__x);
    645 }
    646 
    647 template <class _Tp>
    648 inline _LIBCPP_INLINE_VISIBILITY
    649 constexpr
    650 bool
    651 operator==(nullopt_t, const optional<_Tp>& __x) noexcept
    652 {
    653     return !static_cast<bool>(__x);
    654 }
    655 
    656 template <class _Tp>
    657 inline _LIBCPP_INLINE_VISIBILITY
    658 constexpr
    659 bool
    660 operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
    661 {
    662     return static_cast<bool>(__x);
    663 }
    664 
    665 template <class _Tp>
    666 inline _LIBCPP_INLINE_VISIBILITY
    667 constexpr
    668 bool
    669 operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
    670 {
    671     return static_cast<bool>(__x);
    672 }
    673 
    674 template <class _Tp>
    675 inline _LIBCPP_INLINE_VISIBILITY
    676 constexpr
    677 bool
    678 operator<(const optional<_Tp>&, nullopt_t) noexcept
    679 {
    680     return false;
    681 }
    682 
    683 template <class _Tp>
    684 inline _LIBCPP_INLINE_VISIBILITY
    685 constexpr
    686 bool
    687 operator<(nullopt_t, const optional<_Tp>& __x) noexcept
    688 {
    689     return static_cast<bool>(__x);
    690 }
    691 
    692 template <class _Tp>
    693 inline _LIBCPP_INLINE_VISIBILITY
    694 constexpr
    695 bool
    696 operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
    697 {
    698     return !static_cast<bool>(__x);
    699 }
    700 
    701 template <class _Tp>
    702 inline _LIBCPP_INLINE_VISIBILITY
    703 constexpr
    704 bool
    705 operator<=(nullopt_t, const optional<_Tp>& __x) noexcept
    706 {
    707     return true;
    708 }
    709 
    710 template <class _Tp>
    711 inline _LIBCPP_INLINE_VISIBILITY
    712 constexpr
    713 bool
    714 operator>(const optional<_Tp>& __x, nullopt_t) noexcept
    715 {
    716     return static_cast<bool>(__x);
    717 }
    718 
    719 template <class _Tp>
    720 inline _LIBCPP_INLINE_VISIBILITY
    721 constexpr
    722 bool
    723 operator>(nullopt_t, const optional<_Tp>& __x) noexcept
    724 {
    725     return false;
    726 }
    727 
    728 template <class _Tp>
    729 inline _LIBCPP_INLINE_VISIBILITY
    730 constexpr
    731 bool
    732 operator>=(const optional<_Tp>&, nullopt_t) noexcept
    733 {
    734     return true;
    735 }
    736 
    737 template <class _Tp>
    738 inline _LIBCPP_INLINE_VISIBILITY
    739 constexpr
    740 bool
    741 operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
    742 {
    743     return !static_cast<bool>(__x);
    744 }
    745 
    746 // Comparisons with T
    747 template <class _Tp>
    748 inline _LIBCPP_INLINE_VISIBILITY
    749 constexpr
    750 bool
    751 operator==(const optional<_Tp>& __x, const _Tp& __v)
    752 {
    753     return static_cast<bool>(__x) ? *__x == __v : false;
    754 }
    755 
    756 template <class _Tp>
    757 inline _LIBCPP_INLINE_VISIBILITY
    758 constexpr
    759 bool
    760 operator==(const _Tp& __v, const optional<_Tp>& __x)
    761 {
    762     return static_cast<bool>(__x) ? *__x == __v : false;
    763 }
    764 
    765 template <class _Tp>
    766 inline _LIBCPP_INLINE_VISIBILITY
    767 constexpr
    768 bool
    769 operator!=(const optional<_Tp>& __x, const _Tp& __v)
    770 {
    771     return static_cast<bool>(__x) ? !(*__x == __v) : true;
    772 }
    773 
    774 template <class _Tp>
    775 inline _LIBCPP_INLINE_VISIBILITY
    776 constexpr
    777 bool
    778 operator!=(const _Tp& __v, const optional<_Tp>& __x)
    779 {
    780     return static_cast<bool>(__x) ? !(*__x == __v) : true;
    781 }
    782 
    783 template <class _Tp>
    784 inline _LIBCPP_INLINE_VISIBILITY
    785 constexpr
    786 bool
    787 operator<(const optional<_Tp>& __x, const _Tp& __v)
    788 {
    789     return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
    790 }
    791 
    792 template <class _Tp>
    793 inline _LIBCPP_INLINE_VISIBILITY
    794 constexpr
    795 bool
    796 operator<(const _Tp& __v, const optional<_Tp>& __x)
    797 {
    798     return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
    799 }
    800 
    801 template <class _Tp>
    802 inline _LIBCPP_INLINE_VISIBILITY
    803 constexpr
    804 bool
    805 operator<=(const optional<_Tp>& __x, const _Tp& __v)
    806 {
    807     return !(__x > __v);
    808 }
    809 
    810 template <class _Tp>
    811 inline _LIBCPP_INLINE_VISIBILITY
    812 constexpr
    813 bool
    814 operator<=(const _Tp& __v, const optional<_Tp>& __x)
    815 {
    816     return !(__v > __x);
    817 }
    818 
    819 template <class _Tp>
    820 inline _LIBCPP_INLINE_VISIBILITY
    821 constexpr
    822 bool
    823 operator>(const optional<_Tp>& __x, const _Tp& __v)
    824 {
    825     return static_cast<bool>(__x) ? __v < __x : false;
    826 }
    827 
    828 template <class _Tp>
    829 inline _LIBCPP_INLINE_VISIBILITY
    830 constexpr
    831 bool
    832 operator>(const _Tp& __v, const optional<_Tp>& __x)
    833 {
    834     return static_cast<bool>(__x) ? __x < __v : true;
    835 }
    836 
    837 template <class _Tp>
    838 inline _LIBCPP_INLINE_VISIBILITY
    839 constexpr
    840 bool
    841 operator>=(const optional<_Tp>& __x, const _Tp& __v)
    842 {
    843     return !(__x < __v);
    844 }
    845 
    846 template <class _Tp>
    847 inline _LIBCPP_INLINE_VISIBILITY
    848 constexpr
    849 bool
    850 operator>=(const _Tp& __v, const optional<_Tp>& __x)
    851 {
    852     return !(__v < __x);
    853 }
    854 
    855 
    856 template <class _Tp>
    857 inline _LIBCPP_INLINE_VISIBILITY
    858 void
    859 swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
    860 {
    861     __x.swap(__y);
    862 }
    863 
    864 template <class _Tp>
    865 inline _LIBCPP_INLINE_VISIBILITY
    866 constexpr
    867 optional<typename decay<_Tp>::type>
    868 make_optional(_Tp&& __v)
    869 {
    870     return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
    871 }
    872 
    873 _LIBCPP_END_NAMESPACE_LFTS
    874 
    875 _LIBCPP_BEGIN_NAMESPACE_STD
    876 
    877 template <class _Tp>
    878 struct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
    879 {
    880     typedef std::experimental::optional<_Tp> argument_type;
    881     typedef size_t        result_type;
    882 
    883     _LIBCPP_INLINE_VISIBILITY
    884     result_type operator()(const argument_type& __opt) const _NOEXCEPT
    885     {
    886         return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
    887     }
    888 };
    889 
    890 _LIBCPP_END_NAMESPACE_STD
    891 
    892 #endif  // _LIBCPP_STD_VER > 11
    893 
    894 #endif  // _LIBCPP_OPTIONAL
    895