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 #include <initializer_list>
     20 
     21 namespace std { namespace experimental {
     22 
     23 // optional for object types
     24 template <class T>
     25 class optional
     26 {
     27 public:
     28     typedef T value_type;
     29 
     30     // constructors
     31     constexpr optional() noexcept;
     32     constexpr optional(nullopt_t) noexcept;
     33     optional(const optional&);
     34     optional(optional&&) noexcept(is_nothrow_move_constructible<T>::value);
     35     constexpr optional(const T&);
     36     constexpr optional(T&&);
     37     template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
     38     template <class U, class... Args>
     39         constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
     40 
     41     // destructor
     42     ~optional();
     43 
     44     // assignment
     45     optional& operator=(nullopt_t) noexcept;
     46     optional& operator=(const optional&);
     47     optional& operator=(optional&&)
     48         noexcept(is_nothrow_move_assignable<T>::value &&
     49                  is_nothrow_move_constructible<T>::value);
     50     template <class U> optional& operator=(U&&);
     51     template <class... Args> void emplace(Args&&...);
     52     template <class U, class... Args> void emplace(initializer_list<U>, Args&&...);
     53 
     54     // swap
     55     void swap(optional&)
     56         noexcept(is_nothrow_move_constructible<T>::value &&
     57                  noexcept(swap(declval<T&>(), declval<T&>())));
     58 
     59     // observers
     60     constexpr T const* operator->() const;
     61     T* operator->();
     62     constexpr T const& operator*() const;
     63     T& operator*();
     64     constexpr explicit operator bool() const noexcept;
     65     constexpr T const& value() const;
     66     T& value();
     67     template <class U> constexpr T value_or(U&&) const&;
     68     template <class U> T value_or(U&&) &&;
     69 };
     70 
     71 // In-place construction
     72 struct in_place_t{};
     73 constexpr in_place_t in_place{};
     74 
     75 // Disengaged state indicator
     76 struct nullopt_t{see below};
     77 constexpr nullopt_t nullopt(unspecified);
     78 
     79 // class bad_optional_access
     80 class bad_optional_access
     81     : public logic_error
     82 {
     83 public:
     84     explicit bad_optional_access(const string& what_arg);
     85     explicit bad_optional_access(const char* what_arg);
     86 };
     87 
     88 // Relational operators
     89 template <class T> constexpr bool operator==(const optional<T>&, const optional<T>&);
     90 template <class T> constexpr bool operator< (const optional<T>&, const optional<T>&);
     91 
     92 // Comparison with nullopt
     93 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
     94 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
     95 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
     96 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
     97 
     98 // Comparison with T
     99 template <class T> constexpr bool operator==(const optional<T>&, const T&);
    100 template <class T> constexpr bool operator==(const T&, const optional<T>&);
    101 template <class T> constexpr bool operator<(const optional<T>&, const T&);
    102 template <class T> constexpr bool operator<(const T&, const optional<T>&);
    103 
    104 // Specialized algorithms
    105 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
    106 template <class T> constexpr optional<typename decay<T>::type> make_optional(T&&);
    107 
    108 // hash support
    109 template <class T> struct hash;
    110 template <class T> struct hash<optional<T>>;
    111 
    112 }}  // std::experimental
    113 
    114 */
    115 
    116 #include <__config>
    117 #include <functional>
    118 #include <stdexcept>
    119 
    120 namespace std { namespace experimental {
    121 
    122 class _LIBCPP_EXCEPTION_ABI bad_optional_access
    123     : public logic_error
    124 {
    125 public:
    126 #if _LIBCPP_STD_VER > 11
    127     _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const string& __arg)
    128         : logic_error(__arg) {}
    129     _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const char* __arg)
    130         : logic_error(__arg) {}
    131     _LIBCPP_INLINE_VISIBILITY bad_optional_access(const bad_optional_access&) noexcept = default;
    132     _LIBCPP_INLINE_VISIBILITY bad_optional_access& operator=(const bad_optional_access&) noexcept = default;
    133 #else
    134 private:
    135     bad_optional_access(const bad_optional_access&);
    136     bad_optional_access& operator=(const bad_optional_access&);
    137 public:
    138 #endif  // _LIBCPP_STD_VER > 11
    139     // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y
    140     virtual ~bad_optional_access() _NOEXCEPT;
    141 };
    142 
    143 }}  // std::experimental
    144 
    145 #if _LIBCPP_STD_VER > 11
    146 
    147 #include <initializer_list>
    148 #include <type_traits>
    149 #include <new>
    150 #include <__functional_base>
    151 
    152 #include <__undef_min_max>
    153 
    154 #ifdef _LIBCPP_DEBUG
    155 #   include <__debug>
    156 #else
    157 #   define _LIBCPP_ASSERT(x, m) ((void)0)
    158 #endif
    159 
    160 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    161 #pragma GCC system_header
    162 #endif
    163 
    164 namespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
    165 
    166 struct in_place_t {};
    167 constexpr in_place_t in_place{};
    168 
    169 struct nullopt_t
    170 {
    171     explicit constexpr nullopt_t(int) noexcept {}
    172 };
    173 
    174 constexpr nullopt_t nullopt{0};
    175 
    176 template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
    177 class __optional_storage
    178 {
    179 protected:
    180     typedef _Tp value_type;
    181     union
    182     {
    183         char __null_state_;
    184         value_type __val_;
    185     };
    186     bool __engaged_ = false;
    187 
    188     _LIBCPP_INLINE_VISIBILITY
    189     ~__optional_storage()
    190     {
    191         if (__engaged_)
    192             __val_.~value_type();
    193     }
    194 
    195     _LIBCPP_INLINE_VISIBILITY
    196     constexpr __optional_storage() noexcept
    197         :  __null_state_('\0') {}
    198 
    199     _LIBCPP_INLINE_VISIBILITY
    200     __optional_storage(const __optional_storage& __x)
    201         :  __engaged_(__x.__engaged_)
    202         {
    203             if (__engaged_)
    204                 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
    205         }
    206 
    207     _LIBCPP_INLINE_VISIBILITY
    208     __optional_storage(__optional_storage&& __x)
    209                       noexcept(is_nothrow_move_constructible<value_type>::value)
    210         :  __engaged_(__x.__engaged_)
    211         {
    212             if (__engaged_)
    213                 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
    214         }
    215 
    216     _LIBCPP_INLINE_VISIBILITY
    217     constexpr __optional_storage(const value_type& __v)
    218         :  __val_(__v),
    219            __engaged_(true) {}
    220 
    221     _LIBCPP_INLINE_VISIBILITY
    222     constexpr __optional_storage(value_type&& __v)
    223         :  __val_(_VSTD::move(__v)),
    224            __engaged_(true) {}
    225 
    226     template <class... _Args>
    227     _LIBCPP_INLINE_VISIBILITY
    228     constexpr
    229     explicit __optional_storage(in_place_t, _Args&&... __args)
    230        :  __val_(_VSTD::forward<_Args>(__args)...),
    231            __engaged_(true) {}
    232 };
    233 
    234 template <class _Tp>
    235 class __optional_storage<_Tp, true>
    236 {
    237 protected:
    238     typedef _Tp value_type;
    239     union
    240     {
    241         char __null_state_;
    242         value_type __val_;
    243     };
    244     bool __engaged_ = false;
    245 
    246     _LIBCPP_INLINE_VISIBILITY
    247     constexpr __optional_storage() noexcept
    248         :  __null_state_('\0') {}
    249 
    250     _LIBCPP_INLINE_VISIBILITY
    251     __optional_storage(const __optional_storage& __x)
    252         :  __engaged_(__x.__engaged_)
    253         {
    254             if (__engaged_)
    255                 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
    256         }
    257 
    258     _LIBCPP_INLINE_VISIBILITY
    259     __optional_storage(__optional_storage&& __x)
    260                       noexcept(is_nothrow_move_constructible<value_type>::value)
    261         :  __engaged_(__x.__engaged_)
    262         {
    263             if (__engaged_)
    264                 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
    265         }
    266 
    267     _LIBCPP_INLINE_VISIBILITY
    268     constexpr __optional_storage(const value_type& __v)
    269         :  __val_(__v),
    270            __engaged_(true) {}
    271 
    272     _LIBCPP_INLINE_VISIBILITY
    273     constexpr __optional_storage(value_type&& __v)
    274         :  __val_(_VSTD::move(__v)),
    275            __engaged_(true) {}
    276 
    277     template <class... _Args>
    278     _LIBCPP_INLINE_VISIBILITY
    279     constexpr
    280     explicit __optional_storage(in_place_t, _Args&&... __args)
    281        :  __val_(_VSTD::forward<_Args>(__args)...),
    282            __engaged_(true) {}
    283 };
    284 
    285 template <class _Tp>
    286 class optional
    287     : private __optional_storage<_Tp>
    288 {
    289     typedef __optional_storage<_Tp> __base;
    290 public:
    291     typedef _Tp value_type;
    292 
    293     static_assert(!is_reference<value_type>::value,
    294               "Instantiation of optional with a reference type is ill-formed.");
    295     static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value,
    296               "Instantiation of optional with a in_place_t type is ill-formed.");
    297     static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value,
    298               "Instantiation of optional with a nullopt_t type is ill-formed.");
    299     static_assert(is_object<value_type>::value,
    300         "Instantiation of optional with a non-object type is undefined behavior.");
    301     static_assert(is_nothrow_destructible<value_type>::value,
    302         "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior.");
    303 
    304     _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
    305     _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
    306     _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
    307     _LIBCPP_INLINE_VISIBILITY ~optional() = default;
    308     _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
    309     _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v)
    310         : __base(__v) {}
    311     _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v)
    312         : __base(_VSTD::move(__v)) {}
    313 
    314     template <class... _Args,
    315               class = typename enable_if
    316                       <
    317                            is_constructible<value_type, _Args...>::value
    318                       >::type
    319              >
    320     _LIBCPP_INLINE_VISIBILITY
    321     constexpr
    322     explicit optional(in_place_t, _Args&&... __args)
    323         : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
    324 
    325     template <class _Up, class... _Args,
    326               class = typename enable_if
    327                       <
    328                            is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    329                       >::type
    330              >
    331     _LIBCPP_INLINE_VISIBILITY
    332     constexpr
    333     explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
    334         : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
    335 
    336     _LIBCPP_INLINE_VISIBILITY
    337     optional& operator=(nullopt_t) noexcept
    338     {
    339         if (this->__engaged_)
    340         {
    341             this->__val_.~value_type();
    342             this->__engaged_ = false;
    343         }
    344         return *this;
    345     }
    346 
    347     _LIBCPP_INLINE_VISIBILITY
    348     optional&
    349     operator=(const optional& __opt)
    350     {
    351         if (this->__engaged_ == __opt.__engaged_)
    352         {
    353             if (this->__engaged_)
    354                 this->__val_ = __opt.__val_;
    355         }
    356         else
    357         {
    358             if (this->__engaged_)
    359                 this->__val_.~value_type();
    360             else
    361                 ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
    362             this->__engaged_ = __opt.__engaged_;
    363         }
    364         return *this;
    365     }
    366 
    367     _LIBCPP_INLINE_VISIBILITY
    368     optional&
    369     operator=(optional&& __opt)
    370         noexcept(is_nothrow_move_assignable<value_type>::value &&
    371                  is_nothrow_move_constructible<value_type>::value)
    372     {
    373         if (this->__engaged_ == __opt.__engaged_)
    374         {
    375             if (this->__engaged_)
    376                 this->__val_ = _VSTD::move(__opt.__val_);
    377         }
    378         else
    379         {
    380             if (this->__engaged_)
    381                 this->__val_.~value_type();
    382             else
    383                 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
    384             this->__engaged_ = __opt.__engaged_;
    385         }
    386         return *this;
    387     }
    388 
    389     template <class _Up,
    390               class = typename enable_if
    391                       <
    392                           is_same<typename remove_reference<_Up>::type, value_type>::value &&
    393                           is_constructible<value_type, _Up>::value &&
    394                           is_assignable<value_type&, _Up>::value
    395                       >::type
    396              >
    397     _LIBCPP_INLINE_VISIBILITY
    398     optional&
    399     operator=(_Up&& __v)
    400     {
    401         if (this->__engaged_)
    402             this->__val_ = _VSTD::forward<_Up>(__v);
    403         else
    404         {
    405             ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
    406             this->__engaged_ = true;
    407         }
    408         return *this;
    409     }
    410 
    411     template <class... _Args,
    412               class = typename enable_if
    413                       <
    414                           is_constructible<value_type, _Args...>::value
    415                       >::type
    416              >
    417     _LIBCPP_INLINE_VISIBILITY
    418     void
    419     emplace(_Args&&... __args)
    420     {
    421         *this = nullopt;
    422         ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
    423         this->__engaged_ = true;
    424     }
    425 
    426     template <class _Up, class... _Args,
    427               class = typename enable_if
    428                       <
    429                           is_constructible<value_type, initializer_list<_Up>&, _Args...>::value
    430                       >::type
    431              >
    432     _LIBCPP_INLINE_VISIBILITY
    433     void
    434     emplace(initializer_list<_Up> __il, _Args&&... __args)
    435     {
    436         *this = nullopt;
    437         ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
    438         this->__engaged_ = true;
    439     }
    440 
    441     _LIBCPP_INLINE_VISIBILITY
    442     void
    443     swap(optional& __opt)
    444         noexcept(is_nothrow_move_constructible<value_type>::value &&
    445                  __is_nothrow_swappable<value_type>::value)
    446     {
    447         using _VSTD::swap;
    448         if (this->__engaged_ == __opt.__engaged_)
    449         {
    450             if (this->__engaged_)
    451                 swap(this->__val_, __opt.__val_);
    452         }
    453         else
    454         {
    455             if (this->__engaged_)
    456             {
    457                 ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
    458                 this->__val_.~value_type();
    459             }
    460             else
    461             {
    462                 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
    463                 __opt.__val_.~value_type();
    464             }
    465             swap(this->__engaged_, __opt.__engaged_);
    466         }
    467     }
    468 
    469     _LIBCPP_INLINE_VISIBILITY
    470     constexpr
    471     value_type const*
    472     operator->() const
    473     {
    474         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    475         return __operator_arrow(__has_operator_addressof<value_type>{});
    476     }
    477 
    478     _LIBCPP_INLINE_VISIBILITY
    479     value_type*
    480     operator->()
    481     {
    482         _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value");
    483         return _VSTD::addressof(this->__val_);
    484     }
    485 
    486     _LIBCPP_INLINE_VISIBILITY
    487     constexpr
    488     const value_type&
    489     operator*() const
    490     {
    491         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    492         return this->__val_;
    493     }
    494 
    495     _LIBCPP_INLINE_VISIBILITY
    496     value_type&
    497     operator*()
    498     {
    499         _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value");
    500         return this->__val_;
    501     }
    502 
    503     _LIBCPP_INLINE_VISIBILITY
    504     constexpr explicit operator bool() const noexcept {return this->__engaged_;}
    505 
    506     _LIBCPP_INLINE_VISIBILITY
    507     constexpr value_type const& value() const
    508     {
    509         if (!this->__engaged_)
    510             throw bad_optional_access("optional<T>::value: not engaged");
    511         return this->__val_;
    512     }
    513 
    514     _LIBCPP_INLINE_VISIBILITY
    515     value_type& value()
    516     {
    517         if (!this->__engaged_)
    518             throw bad_optional_access("optional<T>::value: not engaged");
    519         return this->__val_;
    520     }
    521 
    522     template <class _Up>
    523     _LIBCPP_INLINE_VISIBILITY
    524     constexpr value_type value_or(_Up&& __v) const&
    525     {
    526         static_assert(is_copy_constructible<value_type>::value,
    527                       "optional<T>::value_or: T must be copy constructible");
    528         static_assert(is_convertible<_Up, value_type>::value,
    529                       "optional<T>::value_or: U must be convertible to T");
    530         return this->__engaged_ ? this->__val_ :
    531                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    532     }
    533 
    534     template <class _Up>
    535     _LIBCPP_INLINE_VISIBILITY
    536     value_type value_or(_Up&& __v) &&
    537     {
    538         static_assert(is_move_constructible<value_type>::value,
    539                       "optional<T>::value_or: T must be move constructible");
    540         static_assert(is_convertible<_Up, value_type>::value,
    541                       "optional<T>::value_or: U must be convertible to T");
    542         return this->__engaged_ ? _VSTD::move(this->__val_) :
    543                                   static_cast<value_type>(_VSTD::forward<_Up>(__v));
    544     }
    545 
    546 private:
    547     _LIBCPP_INLINE_VISIBILITY
    548     value_type const*
    549     __operator_arrow(true_type) const
    550     {
    551         return _VSTD::addressof(this->__val_);
    552     }
    553 
    554     _LIBCPP_INLINE_VISIBILITY
    555     constexpr
    556     value_type const*
    557     __operator_arrow(false_type) const
    558     {
    559         return &this->__val_;
    560     }
    561 };
    562 
    563 template <class _Tp>
    564 inline _LIBCPP_INLINE_VISIBILITY
    565 constexpr
    566 bool
    567 operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
    568 {
    569     if (static_cast<bool>(__x) != static_cast<bool>(__y))
    570         return false;
    571     if (!static_cast<bool>(__x))
    572         return true;
    573     return *__x == *__y;
    574 }
    575 
    576 template <class _Tp>
    577 inline _LIBCPP_INLINE_VISIBILITY
    578 constexpr
    579 bool
    580 operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
    581 {
    582     if (!static_cast<bool>(__y))
    583         return false;
    584     if (!static_cast<bool>(__x))
    585         return true;
    586     return less<_Tp>{}(*__x, *__y);
    587 }
    588 
    589 template <class _Tp>
    590 inline _LIBCPP_INLINE_VISIBILITY
    591 constexpr
    592 bool
    593 operator==(const optional<_Tp>& __x, nullopt_t) noexcept
    594 {
    595     return !static_cast<bool>(__x);
    596 }
    597 
    598 template <class _Tp>
    599 inline _LIBCPP_INLINE_VISIBILITY
    600 constexpr
    601 bool
    602 operator==(nullopt_t, const optional<_Tp>& __x) noexcept
    603 {
    604     return !static_cast<bool>(__x);
    605 }
    606 
    607 template <class _Tp>
    608 inline _LIBCPP_INLINE_VISIBILITY
    609 constexpr
    610 bool
    611 operator<(const optional<_Tp>&, nullopt_t) noexcept
    612 {
    613     return false;
    614 }
    615 
    616 template <class _Tp>
    617 inline _LIBCPP_INLINE_VISIBILITY
    618 constexpr
    619 bool
    620 operator<(nullopt_t, const optional<_Tp>& __x) noexcept
    621 {
    622     return static_cast<bool>(__x);
    623 }
    624 
    625 template <class _Tp>
    626 inline _LIBCPP_INLINE_VISIBILITY
    627 constexpr
    628 bool
    629 operator==(const optional<_Tp>& __x, const _Tp& __v)
    630 {
    631     return static_cast<bool>(__x) ? *__x == __v : false;
    632 }
    633 
    634 template <class _Tp>
    635 inline _LIBCPP_INLINE_VISIBILITY
    636 constexpr
    637 bool
    638 operator==(const _Tp& __v, const optional<_Tp>& __x)
    639 {
    640     return static_cast<bool>(__x) ? *__x == __v : false;
    641 }
    642 
    643 template <class _Tp>
    644 inline _LIBCPP_INLINE_VISIBILITY
    645 constexpr
    646 bool
    647 operator<(const optional<_Tp>& __x, const _Tp& __v)
    648 {
    649     return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true;
    650 }
    651 
    652 template <class _Tp>
    653 inline _LIBCPP_INLINE_VISIBILITY
    654 constexpr
    655 bool
    656 operator<(const _Tp& __v, const optional<_Tp>& __x)
    657 {
    658     return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
    659 }
    660 
    661 template <class _Tp>
    662 inline _LIBCPP_INLINE_VISIBILITY
    663 void
    664 swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
    665 {
    666     __x.swap(__y);
    667 }
    668 
    669 template <class _Tp>
    670 inline _LIBCPP_INLINE_VISIBILITY
    671 constexpr
    672 optional<typename decay<_Tp>::type>
    673 make_optional(_Tp&& __v)
    674 {
    675     return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
    676 }
    677 
    678 }}}  // namespace std::experimental::__library_fundamentals_v1
    679 
    680 _LIBCPP_BEGIN_NAMESPACE_STD
    681 
    682 template <class _Tp>
    683 struct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> >
    684 {
    685     typedef std::experimental::optional<_Tp> argument_type;
    686     typedef size_t        result_type;
    687 
    688     _LIBCPP_INLINE_VISIBILITY
    689     result_type operator()(const argument_type& __opt) const _NOEXCEPT
    690     {
    691         return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
    692     }
    693 };
    694 
    695 _LIBCPP_END_NAMESPACE_STD
    696 
    697 #endif  // _LIBCPP_STD_VER > 11
    698 
    699 #endif  // _LIBCPP_ARRAY
    700