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_EXPERIMENTAL_OPTIONAL
     12 #define _LIBCPP_EXPERIMENTAL_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 #if _LIBCPP_STD_VER > 11
    147 #include <initializer_list>
    148 #include <type_traits>
    149 #include <new>
    150 #include <__functional_base>
    151 #include <__debug>
    152 #endif
    153 
    154 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    155 #pragma GCC system_header
    156 #endif
    157 
    158 _LIBCPP_PUSH_MACROS
    159 #include <__undef_macros>
    160 
    161 
    162 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
    163 class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
    164     : public std::logic_error
    165 {
    166 public:
    167 	bad_optional_access() : std::logic_error("Bad optional Access") {}
    168 
    169 //	Get the key function ~bad_optional_access() into the dylib
    170     virtual ~bad_optional_access() _NOEXCEPT;
    171 };
    172 
    173 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
    174 
    175 
    176 #if _LIBCPP_STD_VER > 11
    177 
    178 _LIBCPP_BEGIN_NAMESPACE_LFTS
    179 
    180 struct in_place_t {};
    181 constexpr in_place_t in_place{};
    182 
    183 struct nullopt_t
    184 {
    185     explicit constexpr nullopt_t(int) noexcept {}
    186 };
    187 
    188 constexpr nullopt_t nullopt{0};
    189 
    190 template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
    191 class __optional_storage
    192 {
    193 protected:
    194     typedef _Tp value_type;
    195     union
    196     {
    197         char __null_state_;
    198         value_type __val_;
    199     };
    200     bool __engaged_ = false;
    201 
    202     _LIBCPP_INLINE_VISIBILITY
    203     ~__optional_storage()
    204     {
    205         if (__engaged_)
    206             __val_.~value_type();
    207     }
    208 
    209     _LIBCPP_INLINE_VISIBILITY
    210     constexpr __optional_storage() noexcept
    211         :  __null_state_('\0') {}
    212 
    213     _LIBCPP_INLINE_VISIBILITY
    214     __optional_storage(const __optional_storage& __x)
    215         :  __engaged_(__x.__engaged_)
    216         {
    217             if (__engaged_)
    218                 ::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_);
    219         }
    220 
    221     _LIBCPP_INLINE_VISIBILITY
    222     __optional_storage(__optional_storage&& __x)
    223                       noexcept(is_nothrow_move_constructible<value_type>::value)
    224         :  __engaged_(__x.__engaged_)
    225         {
    226             if (__engaged_)
    227                 ::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
    228         }
    229 
    230     _LIBCPP_INLINE_VISIBILITY
    231     constexpr __optional_storage(const value_type& __v)
    232         :  __val_(__v),
    233            __engaged_(true) {}
    234 
    235     _LIBCPP_INLINE_VISIBILITY
    236     constexpr __optional_storage(value_type&& __v)
    237         :  __val_(_VSTD::move(__v)),
    238            __engaged_(true) {}
    239 
    240     template <class... _Args>
    241     _LIBCPP_INLINE_VISIBILITY
    242     constexpr
    243     explicit __optional_storage(in_place_t, _Args&&... __args)
    244        :  __val_(_VSTD::forward<_Args>(__args)...),
    245            __engaged_(true) {}
    246 };
    247 
    248 template <class _Tp>
    249 class __optional_storage<_Tp, true>
    250 {
    251 protected:
    252     typedef _Tp value_type;
    253     union
    254     {
    255         char __null_state_;
    256         value_type __val_;
    257     };
    258     bool __engaged_ = false;
    259 
    260     _LIBCPP_INLINE_VISIBILITY
    261     constexpr __optional_storage() noexcept
    262         :  __null_state_('\0') {}
    263 
    264     _LIBCPP_INLINE_VISIBILITY
    265     __optional_storage(const __optional_storage& __x)
    266         :  __engaged_(__x.__engaged_)
    267         {
    268             if (__engaged_)
    269                 ::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_);
    270         }
    271 
    272     _LIBCPP_INLINE_VISIBILITY
    273     __optional_storage(__optional_storage&& __x)
    274                       noexcept(is_nothrow_move_constructible<value_type>::value)
    275         :  __engaged_(__x.__engaged_)
    276         {
    277             if (__engaged_)
    278                 ::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
    279         }
    280 
    281     _LIBCPP_INLINE_VISIBILITY
    282     constexpr __optional_storage(const value_type& __v)
    283         :  __val_(__v),
    284            __engaged_(true) {}
    285 
    286     _LIBCPP_INLINE_VISIBILITY
    287     constexpr __optional_storage(value_type&& __v)
    288         :  __val_(_VSTD::move(__v)),
    289            __engaged_(true) {}
    290 
    291     template <class... _Args>
    292     _LIBCPP_INLINE_VISIBILITY
    293     constexpr
    294     explicit __optional_storage(in_place_t, _Args&&... __args)
    295        :  __val_(_VSTD::forward<_Args>(__args)...),
    296            __engaged_(true) {}
    297 };
    298 
    299 template <class _Tp>
    300 class optional
    301     : private __optional_storage<_Tp>
    302 {
    303     typedef __optional_storage<_Tp> __base;
    304 public:
    305     typedef _Tp value_type;
    306 
    307     static_assert(!is_reference<value_type>::value,
    308               "Instantiation of optional with a reference type is ill-formed.");
    309     static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
    310               "Instantiation of optional with a in_place_t type is ill-formed.");
    311     static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
    312               "Instantiation of optional with a nullopt_t type is ill-formed.");
    313     static_assert(is_object<value_type>::value,
    314         "Instantiation of optional with a non-object type is undefined behavior.");
    315     static_assert(is_nothrow_destructible<value_type>::value,
    316         "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
    317 
    318     _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
    319     _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
    320     _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
    321     _LIBCPP_INLINE_VISIBILITY ~optional() = default;
    322     _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
    323     _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
    324         : __base(__v) {}
    325     _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
    326         : __base(_VSTD::move(__v)) {}
    327 
    328     template <class... _Args,
    329               class = typename enable_if
    330                       <
    331                            is_constructible<value_type, _Args...>::value
    332                       >::type
    333              >
    334     _LIBCPP_INLINE_VISIBILITY
    335     constexpr
    336     explicit optional(in_place_t, _Args&&... __args)
    337         : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
    338 
    339     template <class _Up, class... _Args,
    340               class = typename enable_if
    341                       <
    342                            is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    343                       >::type
    344              >
    345     _LIBCPP_INLINE_VISIBILITY
    346     constexpr
    347     explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
    348         : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
    349 
    350     _LIBCPP_INLINE_VISIBILITY
    351     optional& operator=(nullopt_t) noexcept
    352     {
    353         if (this->__engaged_)
    354         {
    355             this->__val_.~value_type();
    356             this->__engaged_ = false;
    357         }
    358         return *this;
    359     }
    360 
    361     _LIBCPP_INLINE_VISIBILITY
    362     optional&
    363     operator=(const optional& __opt)
    364     {
    365         if (this->__engaged_ == __opt.__engaged_)
    366         {
    367             if (this->__engaged_)
    368                 this->__val_ = __opt.__val_;
    369         }
    370         else
    371         {
    372             if (this->__engaged_)
    373                 this->__val_.~value_type();
    374             else
    375                 ::new((void*)_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
    376             this->__engaged_ = __opt.__engaged_;
    377         }
    378         return *this;
    379     }
    380 
    381     _LIBCPP_INLINE_VISIBILITY
    382     optional&
    383     operator=(optional&& __opt)
    384         noexcept(is_nothrow_move_assignable<value_type>::value &&
    385                  is_nothrow_move_constructible<value_type>::value)
    386     {
    387         if (this->__engaged_ == __opt.__engaged_)
    388         {
    389             if (this->__engaged_)
    390                 this->__val_ = _VSTD::move(__opt.__val_);
    391         }
    392         else
    393         {
    394             if (this->__engaged_)
    395                 this->__val_.~value_type();
    396             else
    397                 ::new((void*)_VSTD::addressof(this->__val_))
    398                     value_type(_VSTD::move(__opt.__val_));
    399             this->__engaged_ = __opt.__engaged_;
    400         }
    401         return *this;
    402     }
    403 
    404     template <class _Up,
    405               class = typename enable_if
    406                       <
    407                           is_same<typename remove_reference<_Up>::type, value_type>::value &&
    408                           is_constructible<value_type, _Up>::value &&
    409                           is_assignable<value_type&, _Up>::value
    410                       >::type
    411              >
    412     _LIBCPP_INLINE_VISIBILITY
    413     optional&
    414     operator=(_Up&& __v)
    415     {
    416         if (this->__engaged_)
    417             this->__val_ = _VSTD::forward<_Up>(__v);
    418         else
    419         {
    420             ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
    421             this->__engaged_ = true;
    422         }
    423         return *this;
    424     }
    425 
    426     template <class... _Args,
    427               class = typename enable_if
    428                       <
    429                           is_constructible<value_type, _Args...>::value
    430                       >::type
    431              >
    432     _LIBCPP_INLINE_VISIBILITY
    433     void
    434     emplace(_Args&&... __args)
    435     {
    436         *this = nullopt;
    437         ::new((void*)_VSTD::addressof(this->__val_))
    438             value_type(_VSTD::forward<_Args>(__args)...);
    439         this->__engaged_ = true;
    440     }
    441 
    442     template <class _Up, class... _Args,
    443               class = typename enable_if
    444                       <
    445                           is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    446                       >::type
    447              >
    448     _LIBCPP_INLINE_VISIBILITY
    449     void
    450     emplace(initializer_list<_Up> __il, _Args&&... __args)
    451     {
    452         *this = nullopt;
    453         ::new((void*)_VSTD::addressof(this->__val_))
    454             value_type(__il, _VSTD::forward<_Args>(__args)...);
    455         this->__engaged_ = true;
    456     }
    457 
    458     _LIBCPP_INLINE_VISIBILITY
    459     void
    460     swap(optional& __opt)
    461         noexcept(is_nothrow_move_constructible<value_type>::value &&
    462                  __is_nothrow_swappable<value_type>::value)
    463     {
    464         using _VSTD::swap;
    465         if (this->__engaged_ == __opt.__engaged_)
    466         {
    467             if (this->__engaged_)
    468                 swap(this->__val_, __opt.__val_);
    469         }
    470         else
    471         {
    472             if (this->__engaged_)
    473             {
    474                 ::new((void*)_VSTD::addressof(__opt.__val_))
    475                     value_type(_VSTD::move(this->__val_));
    476                 this->__val_.~value_type();
    477             }
    478             else
    479             {
    480                 ::new((void*)_VSTD::addressof(this->__val_))
    481                     value_type(_VSTD::move(__opt.__val_));
    482                 __opt.__val_.~value_type();
    483             }
    484             swap(this->__engaged_, __opt.__engaged_);
    485         }
    486     }
    487 
    488     _LIBCPP_INLINE_VISIBILITY
    489     constexpr
    490     value_type const*
    491     operator->() const
    492     {
    493         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    494 #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
    495         return __builtin_addressof(this->__val_);
    496 #else
    497         return __operator_arrow(__has_operator_addressof<value_type>{});
    498 #endif
    499     }
    500 
    501     _LIBCPP_INLINE_VISIBILITY
    502     value_type*
    503     operator->()
    504     {
    505         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    506         return _VSTD::addressof(this->__val_);
    507     }
    508 
    509     _LIBCPP_INLINE_VISIBILITY
    510     constexpr
    511     const value_type&
    512     operator*() const
    513     {
    514         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    515         return this->__val_;
    516     }
    517 
    518     _LIBCPP_INLINE_VISIBILITY
    519     value_type&
    520     operator*()
    521     {
    522         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    523         return this->__val_;
    524     }
    525 
    526     _LIBCPP_INLINE_VISIBILITY
    527     constexpr explicit operator bool() const noexcept {return this->__engaged_;}
    528 
    529 	_LIBCPP_NORETURN _LIBCPP_INLINE_VISIBILITY 
    530 #ifndef _LIBCPP_NO_EXCEPTIONS
    531 _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
    532 #endif
    533 	constexpr void __throw_bad_optional_access() const
    534 	{
    535 #ifndef _LIBCPP_NO_EXCEPTIONS
    536         throw bad_optional_access();
    537 #else
    538         _VSTD::abort();
    539 #endif
    540 	}
    541 	
    542     _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
    543     constexpr value_type const& value() const
    544     {
    545         if (!this->__engaged_)
    546             __throw_bad_optional_access();
    547         return this->__val_;
    548     }
    549 
    550     _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
    551     value_type& value()
    552     {
    553         if (!this->__engaged_)
    554             __throw_bad_optional_access();
    555         return this->__val_;
    556     }
    557 
    558     template <class _Up>
    559     _LIBCPP_INLINE_VISIBILITY
    560     constexpr value_type value_or(_Up&& __v) const&
    561     {
    562         static_assert(is_copy_constructible<value_type>::value,
    563                       "optional<T>::value_or: T must be copy constructible");
    564         static_assert(is_convertible<_Up, value_type>::value,
    565                       "optional<T>::value_or: U must be convertible to T");
    566         return this->__engaged_ ? this->__val_ :
    567                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    568     }
    569 
    570     template <class _Up>
    571     _LIBCPP_INLINE_VISIBILITY
    572     value_type value_or(_Up&& __v) &&
    573     {
    574         static_assert(is_move_constructible<value_type>::value,
    575                       "optional<T>::value_or: T must be move constructible");
    576         static_assert(is_convertible<_Up, value_type>::value,
    577                       "optional<T>::value_or: U must be convertible to T");
    578         return this->__engaged_ ? _VSTD::move(this->__val_) :
    579                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    580     }
    581 
    582 private:
    583     _LIBCPP_INLINE_VISIBILITY
    584     value_type const*
    585     __operator_arrow(true_type) const
    586     {
    587         return _VSTD::addressof(this->__val_);
    588     }
    589 
    590     _LIBCPP_INLINE_VISIBILITY
    591     constexpr
    592     value_type const*
    593     __operator_arrow(false_type) const
    594     {
    595         return &this->__val_;
    596     }
    597 };
    598 
    599 // Comparisons between optionals
    600 template <class _Tp>
    601 inline _LIBCPP_INLINE_VISIBILITY
    602 constexpr
    603 bool
    604 operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
    605 {
    606     if (static_cast<bool>(__x) != static_cast<bool>(__y))
    607         return false;
    608     if (!static_cast<bool>(__x))
    609         return true;
    610     return *__x == *__y;
    611 }
    612 
    613 template <class _Tp>
    614 inline _LIBCPP_INLINE_VISIBILITY
    615 constexpr
    616 bool
    617 operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    618 {
    619     return !(__x == __y);
    620 }
    621 
    622 template <class _Tp>
    623 inline _LIBCPP_INLINE_VISIBILITY
    624 constexpr
    625 bool
    626 operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
    627 {
    628     if (!static_cast<bool>(__y))
    629         return false;
    630     if (!static_cast<bool>(__x))
    631         return true;
    632     return *__x < *__y;
    633 }
    634 
    635 template <class _Tp>
    636 inline _LIBCPP_INLINE_VISIBILITY
    637 constexpr
    638 bool
    639 operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
    640 {
    641     return __y < __x;
    642 }
    643 
    644 template <class _Tp>
    645 inline _LIBCPP_INLINE_VISIBILITY
    646 constexpr
    647 bool
    648 operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    649 {
    650     return !(__y < __x);
    651 }
    652 
    653 template <class _Tp>
    654 inline _LIBCPP_INLINE_VISIBILITY
    655 constexpr
    656 bool
    657 operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    658 {
    659     return !(__x < __y);
    660 }
    661 
    662 
    663 // Comparisons with nullopt
    664 template <class _Tp>
    665 inline _LIBCPP_INLINE_VISIBILITY
    666 constexpr
    667 bool
    668 operator==(const optional<_Tp>& __x, nullopt_t) noexcept
    669 {
    670     return !static_cast<bool>(__x);
    671 }
    672 
    673 template <class _Tp>
    674 inline _LIBCPP_INLINE_VISIBILITY
    675 constexpr
    676 bool
    677 operator==(nullopt_t, const optional<_Tp>& __x) noexcept
    678 {
    679     return !static_cast<bool>(__x);
    680 }
    681 
    682 template <class _Tp>
    683 inline _LIBCPP_INLINE_VISIBILITY
    684 constexpr
    685 bool
    686 operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
    687 {
    688     return static_cast<bool>(__x);
    689 }
    690 
    691 template <class _Tp>
    692 inline _LIBCPP_INLINE_VISIBILITY
    693 constexpr
    694 bool
    695 operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
    696 {
    697     return static_cast<bool>(__x);
    698 }
    699 
    700 template <class _Tp>
    701 inline _LIBCPP_INLINE_VISIBILITY
    702 constexpr
    703 bool
    704 operator<(const optional<_Tp>&, nullopt_t) noexcept
    705 {
    706     return false;
    707 }
    708 
    709 template <class _Tp>
    710 inline _LIBCPP_INLINE_VISIBILITY
    711 constexpr
    712 bool
    713 operator<(nullopt_t, const optional<_Tp>& __x) noexcept
    714 {
    715     return static_cast<bool>(__x);
    716 }
    717 
    718 template <class _Tp>
    719 inline _LIBCPP_INLINE_VISIBILITY
    720 constexpr
    721 bool
    722 operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
    723 {
    724     return !static_cast<bool>(__x);
    725 }
    726 
    727 template <class _Tp>
    728 inline _LIBCPP_INLINE_VISIBILITY
    729 constexpr
    730 bool
    731 operator<=(nullopt_t, const optional<_Tp>&) noexcept
    732 {
    733     return true;
    734 }
    735 
    736 template <class _Tp>
    737 inline _LIBCPP_INLINE_VISIBILITY
    738 constexpr
    739 bool
    740 operator>(const optional<_Tp>& __x, nullopt_t) noexcept
    741 {
    742     return static_cast<bool>(__x);
    743 }
    744 
    745 template <class _Tp>
    746 inline _LIBCPP_INLINE_VISIBILITY
    747 constexpr
    748 bool
    749 operator>(nullopt_t, const optional<_Tp>&) noexcept
    750 {
    751     return false;
    752 }
    753 
    754 template <class _Tp>
    755 inline _LIBCPP_INLINE_VISIBILITY
    756 constexpr
    757 bool
    758 operator>=(const optional<_Tp>&, nullopt_t) noexcept
    759 {
    760     return true;
    761 }
    762 
    763 template <class _Tp>
    764 inline _LIBCPP_INLINE_VISIBILITY
    765 constexpr
    766 bool
    767 operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
    768 {
    769     return !static_cast<bool>(__x);
    770 }
    771 
    772 // Comparisons with T
    773 template <class _Tp>
    774 inline _LIBCPP_INLINE_VISIBILITY
    775 constexpr
    776 bool
    777 operator==(const optional<_Tp>& __x, const _Tp& __v)
    778 {
    779     return static_cast<bool>(__x) ? *__x == __v : false;
    780 }
    781 
    782 template <class _Tp>
    783 inline _LIBCPP_INLINE_VISIBILITY
    784 constexpr
    785 bool
    786 operator==(const _Tp& __v, const optional<_Tp>& __x)
    787 {
    788     return static_cast<bool>(__x) ? *__x == __v : false;
    789 }
    790 
    791 template <class _Tp>
    792 inline _LIBCPP_INLINE_VISIBILITY
    793 constexpr
    794 bool
    795 operator!=(const optional<_Tp>& __x, const _Tp& __v)
    796 {
    797     return static_cast<bool>(__x) ? !(*__x == __v) : true;
    798 }
    799 
    800 template <class _Tp>
    801 inline _LIBCPP_INLINE_VISIBILITY
    802 constexpr
    803 bool
    804 operator!=(const _Tp& __v, const optional<_Tp>& __x)
    805 {
    806     return static_cast<bool>(__x) ? !(*__x == __v) : true;
    807 }
    808 
    809 template <class _Tp>
    810 inline _LIBCPP_INLINE_VISIBILITY
    811 constexpr
    812 bool
    813 operator<(const optional<_Tp>& __x, const _Tp& __v)
    814 {
    815     return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
    816 }
    817 
    818 template <class _Tp>
    819 inline _LIBCPP_INLINE_VISIBILITY
    820 constexpr
    821 bool
    822 operator<(const _Tp& __v, const optional<_Tp>& __x)
    823 {
    824     return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
    825 }
    826 
    827 template <class _Tp>
    828 inline _LIBCPP_INLINE_VISIBILITY
    829 constexpr
    830 bool
    831 operator<=(const optional<_Tp>& __x, const _Tp& __v)
    832 {
    833     return !(__x > __v);
    834 }
    835 
    836 template <class _Tp>
    837 inline _LIBCPP_INLINE_VISIBILITY
    838 constexpr
    839 bool
    840 operator<=(const _Tp& __v, const optional<_Tp>& __x)
    841 {
    842     return !(__v > __x);
    843 }
    844 
    845 template <class _Tp>
    846 inline _LIBCPP_INLINE_VISIBILITY
    847 constexpr
    848 bool
    849 operator>(const optional<_Tp>& __x, const _Tp& __v)
    850 {
    851     return static_cast<bool>(__x) ? __v < __x : false;
    852 }
    853 
    854 template <class _Tp>
    855 inline _LIBCPP_INLINE_VISIBILITY
    856 constexpr
    857 bool
    858 operator>(const _Tp& __v, const optional<_Tp>& __x)
    859 {
    860     return static_cast<bool>(__x) ? __x < __v : true;
    861 }
    862 
    863 template <class _Tp>
    864 inline _LIBCPP_INLINE_VISIBILITY
    865 constexpr
    866 bool
    867 operator>=(const optional<_Tp>& __x, const _Tp& __v)
    868 {
    869     return !(__x < __v);
    870 }
    871 
    872 template <class _Tp>
    873 inline _LIBCPP_INLINE_VISIBILITY
    874 constexpr
    875 bool
    876 operator>=(const _Tp& __v, const optional<_Tp>& __x)
    877 {
    878     return !(__v < __x);
    879 }
    880 
    881 
    882 template <class _Tp>
    883 inline _LIBCPP_INLINE_VISIBILITY
    884 void
    885 swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
    886 {
    887     __x.swap(__y);
    888 }
    889 
    890 template <class _Tp>
    891 inline _LIBCPP_INLINE_VISIBILITY
    892 constexpr
    893 optional<typename decay<_Tp>::type>
    894 make_optional(_Tp&& __v)
    895 {
    896     return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
    897 }
    898 
    899 _LIBCPP_END_NAMESPACE_LFTS
    900 
    901 _LIBCPP_BEGIN_NAMESPACE_STD
    902 
    903 template <class _Tp>
    904 struct _LIBCPP_TEMPLATE_VIS hash<std::experimental::optional<_Tp> >
    905 {
    906     typedef std::experimental::optional<_Tp> argument_type;
    907     typedef size_t        result_type;
    908 
    909     _LIBCPP_INLINE_VISIBILITY
    910     result_type operator()(const argument_type& __opt) const _NOEXCEPT
    911     {
    912         return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
    913     }
    914 };
    915 
    916 _LIBCPP_END_NAMESPACE_STD
    917 
    918 #endif  // _LIBCPP_STD_VER > 11
    919 
    920 _LIBCPP_POP_MACROS
    921 
    922 #endif  // _LIBCPP_EXPERIMENTAL_OPTIONAL
    923