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 
    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((void*)_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((void*)_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((void*)_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((void*)_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((void*)_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((void*)_VSTD::addressof(this->__val_))
    394                     value_type(_VSTD::move(__opt.__val_));
    395             this->__engaged_ = __opt.__engaged_;
    396         }
    397         return *this;
    398     }
    399 
    400     template <class _Up,
    401               class = typename enable_if
    402                       <
    403                           is_same<typename remove_reference<_Up>::type, value_type>::value &&
    404                           is_constructible<value_type, _Up>::value &&
    405                           is_assignable<value_type&, _Up>::value
    406                       >::type
    407              >
    408     _LIBCPP_INLINE_VISIBILITY
    409     optional&
    410     operator=(_Up&& __v)
    411     {
    412         if (this->__engaged_)
    413             this->__val_ = _VSTD::forward<_Up>(__v);
    414         else
    415         {
    416             ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
    417             this->__engaged_ = true;
    418         }
    419         return *this;
    420     }
    421 
    422     template <class... _Args,
    423               class = typename enable_if
    424                       <
    425                           is_constructible<value_type, _Args...>::value
    426                       >::type
    427              >
    428     _LIBCPP_INLINE_VISIBILITY
    429     void
    430     emplace(_Args&&... __args)
    431     {
    432         *this = nullopt;
    433         ::new((void*)_VSTD::addressof(this->__val_))
    434             value_type(_VSTD::forward<_Args>(__args)...);
    435         this->__engaged_ = true;
    436     }
    437 
    438     template <class _Up, class... _Args,
    439               class = typename enable_if
    440                       <
    441                           is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    442                       >::type
    443              >
    444     _LIBCPP_INLINE_VISIBILITY
    445     void
    446     emplace(initializer_list<_Up> __il, _Args&&... __args)
    447     {
    448         *this = nullopt;
    449         ::new((void*)_VSTD::addressof(this->__val_))
    450             value_type(__il, _VSTD::forward<_Args>(__args)...);
    451         this->__engaged_ = true;
    452     }
    453 
    454     _LIBCPP_INLINE_VISIBILITY
    455     void
    456     swap(optional& __opt)
    457         noexcept(is_nothrow_move_constructible<value_type>::value &&
    458                  __is_nothrow_swappable<value_type>::value)
    459     {
    460         using _VSTD::swap;
    461         if (this->__engaged_ == __opt.__engaged_)
    462         {
    463             if (this->__engaged_)
    464                 swap(this->__val_, __opt.__val_);
    465         }
    466         else
    467         {
    468             if (this->__engaged_)
    469             {
    470                 ::new((void*)_VSTD::addressof(__opt.__val_))
    471                     value_type(_VSTD::move(this->__val_));
    472                 this->__val_.~value_type();
    473             }
    474             else
    475             {
    476                 ::new((void*)_VSTD::addressof(this->__val_))
    477                     value_type(_VSTD::move(__opt.__val_));
    478                 __opt.__val_.~value_type();
    479             }
    480             swap(this->__engaged_, __opt.__engaged_);
    481         }
    482     }
    483 
    484     _LIBCPP_INLINE_VISIBILITY
    485     constexpr
    486     value_type const*
    487     operator->() const
    488     {
    489         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    490 #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
    491         return __builtin_addressof(this->__val_);
    492 #else
    493         return __operator_arrow(__has_operator_addressof<value_type>{});
    494 #endif
    495     }
    496 
    497     _LIBCPP_INLINE_VISIBILITY
    498     value_type*
    499     operator->()
    500     {
    501         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    502         return _VSTD::addressof(this->__val_);
    503     }
    504 
    505     _LIBCPP_INLINE_VISIBILITY
    506     constexpr
    507     const value_type&
    508     operator*() const
    509     {
    510         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    511         return this->__val_;
    512     }
    513 
    514     _LIBCPP_INLINE_VISIBILITY
    515     value_type&
    516     operator*()
    517     {
    518         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    519         return this->__val_;
    520     }
    521 
    522     _LIBCPP_INLINE_VISIBILITY
    523     constexpr explicit operator bool() const noexcept {return this->__engaged_;}
    524 
    525 	_LIBCPP_NORETURN _LIBCPP_INLINE_VISIBILITY 
    526 	constexpr void __throw_bad_optional_access() const
    527 	{
    528 #ifndef _LIBCPP_NO_EXCEPTIONS
    529         throw bad_optional_access();
    530 #else
    531         _VSTD::abort();
    532 #endif
    533 	}
    534 	
    535     _LIBCPP_INLINE_VISIBILITY
    536     constexpr value_type const& value() const
    537     {
    538         if (!this->__engaged_)
    539             __throw_bad_optional_access();
    540         return this->__val_;
    541     }
    542 
    543     _LIBCPP_INLINE_VISIBILITY
    544     value_type& value()
    545     {
    546         if (!this->__engaged_)
    547             __throw_bad_optional_access();
    548         return this->__val_;
    549     }
    550 
    551     template <class _Up>
    552     _LIBCPP_INLINE_VISIBILITY
    553     constexpr value_type value_or(_Up&& __v) const&
    554     {
    555         static_assert(is_copy_constructible<value_type>::value,
    556                       "optional<T>::value_or: T must be copy constructible");
    557         static_assert(is_convertible<_Up, value_type>::value,
    558                       "optional<T>::value_or: U must be convertible to T");
    559         return this->__engaged_ ? this->__val_ :
    560                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    561     }
    562 
    563     template <class _Up>
    564     _LIBCPP_INLINE_VISIBILITY
    565     value_type value_or(_Up&& __v) &&
    566     {
    567         static_assert(is_move_constructible<value_type>::value,
    568                       "optional<T>::value_or: T must be move constructible");
    569         static_assert(is_convertible<_Up, value_type>::value,
    570                       "optional<T>::value_or: U must be convertible to T");
    571         return this->__engaged_ ? _VSTD::move(this->__val_) :
    572                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    573     }
    574 
    575 private:
    576     _LIBCPP_INLINE_VISIBILITY
    577     value_type const*
    578     __operator_arrow(true_type) const
    579     {
    580         return _VSTD::addressof(this->__val_);
    581     }
    582 
    583     _LIBCPP_INLINE_VISIBILITY
    584     constexpr
    585     value_type const*
    586     __operator_arrow(false_type) const
    587     {
    588         return &this->__val_;
    589     }
    590 };
    591 
    592 // Comparisons between optionals
    593 template <class _Tp>
    594 inline _LIBCPP_INLINE_VISIBILITY
    595 constexpr
    596 bool
    597 operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
    598 {
    599     if (static_cast<bool>(__x) != static_cast<bool>(__y))
    600         return false;
    601     if (!static_cast<bool>(__x))
    602         return true;
    603     return *__x == *__y;
    604 }
    605 
    606 template <class _Tp>
    607 inline _LIBCPP_INLINE_VISIBILITY
    608 constexpr
    609 bool
    610 operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    611 {
    612     return !(__x == __y);
    613 }
    614 
    615 template <class _Tp>
    616 inline _LIBCPP_INLINE_VISIBILITY
    617 constexpr
    618 bool
    619 operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
    620 {
    621     if (!static_cast<bool>(__y))
    622         return false;
    623     if (!static_cast<bool>(__x))
    624         return true;
    625     return *__x < *__y;
    626 }
    627 
    628 template <class _Tp>
    629 inline _LIBCPP_INLINE_VISIBILITY
    630 constexpr
    631 bool
    632 operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
    633 {
    634     return __y < __x;
    635 }
    636 
    637 template <class _Tp>
    638 inline _LIBCPP_INLINE_VISIBILITY
    639 constexpr
    640 bool
    641 operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    642 {
    643     return !(__y < __x);
    644 }
    645 
    646 template <class _Tp>
    647 inline _LIBCPP_INLINE_VISIBILITY
    648 constexpr
    649 bool
    650 operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
    651 {
    652     return !(__x < __y);
    653 }
    654 
    655 
    656 // Comparisons with nullopt
    657 template <class _Tp>
    658 inline _LIBCPP_INLINE_VISIBILITY
    659 constexpr
    660 bool
    661 operator==(const optional<_Tp>& __x, nullopt_t) noexcept
    662 {
    663     return !static_cast<bool>(__x);
    664 }
    665 
    666 template <class _Tp>
    667 inline _LIBCPP_INLINE_VISIBILITY
    668 constexpr
    669 bool
    670 operator==(nullopt_t, const optional<_Tp>& __x) noexcept
    671 {
    672     return !static_cast<bool>(__x);
    673 }
    674 
    675 template <class _Tp>
    676 inline _LIBCPP_INLINE_VISIBILITY
    677 constexpr
    678 bool
    679 operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
    680 {
    681     return static_cast<bool>(__x);
    682 }
    683 
    684 template <class _Tp>
    685 inline _LIBCPP_INLINE_VISIBILITY
    686 constexpr
    687 bool
    688 operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
    689 {
    690     return static_cast<bool>(__x);
    691 }
    692 
    693 template <class _Tp>
    694 inline _LIBCPP_INLINE_VISIBILITY
    695 constexpr
    696 bool
    697 operator<(const optional<_Tp>&, nullopt_t) noexcept
    698 {
    699     return false;
    700 }
    701 
    702 template <class _Tp>
    703 inline _LIBCPP_INLINE_VISIBILITY
    704 constexpr
    705 bool
    706 operator<(nullopt_t, const optional<_Tp>& __x) noexcept
    707 {
    708     return static_cast<bool>(__x);
    709 }
    710 
    711 template <class _Tp>
    712 inline _LIBCPP_INLINE_VISIBILITY
    713 constexpr
    714 bool
    715 operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
    716 {
    717     return !static_cast<bool>(__x);
    718 }
    719 
    720 template <class _Tp>
    721 inline _LIBCPP_INLINE_VISIBILITY
    722 constexpr
    723 bool
    724 operator<=(nullopt_t, const optional<_Tp>&) noexcept
    725 {
    726     return true;
    727 }
    728 
    729 template <class _Tp>
    730 inline _LIBCPP_INLINE_VISIBILITY
    731 constexpr
    732 bool
    733 operator>(const optional<_Tp>& __x, nullopt_t) noexcept
    734 {
    735     return static_cast<bool>(__x);
    736 }
    737 
    738 template <class _Tp>
    739 inline _LIBCPP_INLINE_VISIBILITY
    740 constexpr
    741 bool
    742 operator>(nullopt_t, const optional<_Tp>&) noexcept
    743 {
    744     return false;
    745 }
    746 
    747 template <class _Tp>
    748 inline _LIBCPP_INLINE_VISIBILITY
    749 constexpr
    750 bool
    751 operator>=(const optional<_Tp>&, nullopt_t) noexcept
    752 {
    753     return true;
    754 }
    755 
    756 template <class _Tp>
    757 inline _LIBCPP_INLINE_VISIBILITY
    758 constexpr
    759 bool
    760 operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
    761 {
    762     return !static_cast<bool>(__x);
    763 }
    764 
    765 // Comparisons with T
    766 template <class _Tp>
    767 inline _LIBCPP_INLINE_VISIBILITY
    768 constexpr
    769 bool
    770 operator==(const optional<_Tp>& __x, const _Tp& __v)
    771 {
    772     return static_cast<bool>(__x) ? *__x == __v : false;
    773 }
    774 
    775 template <class _Tp>
    776 inline _LIBCPP_INLINE_VISIBILITY
    777 constexpr
    778 bool
    779 operator==(const _Tp& __v, const optional<_Tp>& __x)
    780 {
    781     return static_cast<bool>(__x) ? *__x == __v : false;
    782 }
    783 
    784 template <class _Tp>
    785 inline _LIBCPP_INLINE_VISIBILITY
    786 constexpr
    787 bool
    788 operator!=(const optional<_Tp>& __x, const _Tp& __v)
    789 {
    790     return static_cast<bool>(__x) ? !(*__x == __v) : true;
    791 }
    792 
    793 template <class _Tp>
    794 inline _LIBCPP_INLINE_VISIBILITY
    795 constexpr
    796 bool
    797 operator!=(const _Tp& __v, const optional<_Tp>& __x)
    798 {
    799     return static_cast<bool>(__x) ? !(*__x == __v) : true;
    800 }
    801 
    802 template <class _Tp>
    803 inline _LIBCPP_INLINE_VISIBILITY
    804 constexpr
    805 bool
    806 operator<(const optional<_Tp>& __x, const _Tp& __v)
    807 {
    808     return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
    809 }
    810 
    811 template <class _Tp>
    812 inline _LIBCPP_INLINE_VISIBILITY
    813 constexpr
    814 bool
    815 operator<(const _Tp& __v, const optional<_Tp>& __x)
    816 {
    817     return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
    818 }
    819 
    820 template <class _Tp>
    821 inline _LIBCPP_INLINE_VISIBILITY
    822 constexpr
    823 bool
    824 operator<=(const optional<_Tp>& __x, const _Tp& __v)
    825 {
    826     return !(__x > __v);
    827 }
    828 
    829 template <class _Tp>
    830 inline _LIBCPP_INLINE_VISIBILITY
    831 constexpr
    832 bool
    833 operator<=(const _Tp& __v, const optional<_Tp>& __x)
    834 {
    835     return !(__v > __x);
    836 }
    837 
    838 template <class _Tp>
    839 inline _LIBCPP_INLINE_VISIBILITY
    840 constexpr
    841 bool
    842 operator>(const optional<_Tp>& __x, const _Tp& __v)
    843 {
    844     return static_cast<bool>(__x) ? __v < __x : false;
    845 }
    846 
    847 template <class _Tp>
    848 inline _LIBCPP_INLINE_VISIBILITY
    849 constexpr
    850 bool
    851 operator>(const _Tp& __v, const optional<_Tp>& __x)
    852 {
    853     return static_cast<bool>(__x) ? __x < __v : true;
    854 }
    855 
    856 template <class _Tp>
    857 inline _LIBCPP_INLINE_VISIBILITY
    858 constexpr
    859 bool
    860 operator>=(const optional<_Tp>& __x, const _Tp& __v)
    861 {
    862     return !(__x < __v);
    863 }
    864 
    865 template <class _Tp>
    866 inline _LIBCPP_INLINE_VISIBILITY
    867 constexpr
    868 bool
    869 operator>=(const _Tp& __v, const optional<_Tp>& __x)
    870 {
    871     return !(__v < __x);
    872 }
    873 
    874 
    875 template <class _Tp>
    876 inline _LIBCPP_INLINE_VISIBILITY
    877 void
    878 swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
    879 {
    880     __x.swap(__y);
    881 }
    882 
    883 template <class _Tp>
    884 inline _LIBCPP_INLINE_VISIBILITY
    885 constexpr
    886 optional<typename decay<_Tp>::type>
    887 make_optional(_Tp&& __v)
    888 {
    889     return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
    890 }
    891 
    892 _LIBCPP_END_NAMESPACE_LFTS
    893 
    894 _LIBCPP_BEGIN_NAMESPACE_STD
    895 
    896 template <class _Tp>
    897 struct _LIBCPP_TEMPLATE_VIS hash<std::experimental::optional<_Tp> >
    898 {
    899     typedef std::experimental::optional<_Tp> argument_type;
    900     typedef size_t        result_type;
    901 
    902     _LIBCPP_INLINE_VISIBILITY
    903     result_type operator()(const argument_type& __opt) const _NOEXCEPT
    904     {
    905         return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
    906     }
    907 };
    908 
    909 _LIBCPP_END_NAMESPACE_STD
    910 
    911 #endif  // _LIBCPP_STD_VER > 11
    912 
    913 #endif  // _LIBCPP_EXPERIMENTAL_OPTIONAL
    914