Home | History | Annotate | Line # | Download | only in experimental
      1 // <experimental/optional> -*- C++ -*-
      2 
      3 // Copyright (C) 2013-2022 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file experimental/optional
     26  *  This is a TS C++ Library header.
     27  *  @ingroup libfund-ts
     28  */
     29 
     30 #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
     31 #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
     32 
     33 #if __cplusplus >= 201402L
     34 
     35 #include <type_traits>
     36 #include <stdexcept>
     37 #include <new>
     38 #include <initializer_list>
     39 #include <bits/functexcept.h>
     40 #include <bits/functional_hash.h>
     41 #include <bits/enable_special_members.h>
     42 #include <bits/move.h>
     43 #include <experimental/bits/lfts_config.h>
     44 
     45 namespace std _GLIBCXX_VISIBILITY(default)
     46 {
     47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     48 
     49 namespace experimental
     50 {
     51 inline namespace fundamentals_v1
     52 {
     53   /**
     54    * @defgroup optional Optional values
     55    * @ingroup libfund-ts
     56    *
     57    * Class template for optional values and surrounding facilities, as
     58    * described in n3793 "A proposal to add a utility class to represent
     59    * optional objects (Revision 5)".
     60    *
     61    * @{
     62    */
     63 
     64 #define __cpp_lib_experimental_optional 201411
     65 
     66   // All subsequent [X.Y.n] references are against n3793.
     67 
     68   // [X.Y.4]
     69   template<typename _Tp>
     70     class optional;
     71 
     72   // [X.Y.5]
     73   /// Tag type for in-place construction.
     74   struct in_place_t { };
     75 
     76   /// Tag for in-place construction.
     77   constexpr in_place_t in_place { };
     78 
     79   // [X.Y.6]
     80   /// Tag type to disengage optional objects.
     81   struct nullopt_t
     82   {
     83     // Do not user-declare default constructor at all for
     84     // optional_value = {} syntax to work.
     85     // nullopt_t() = delete;
     86 
     87     // Used for constructing nullopt.
     88     enum class _Construct { _Token };
     89 
     90     // Must be constexpr for nullopt_t to be literal.
     91     explicit constexpr nullopt_t(_Construct) { }
     92   };
     93 
     94   // [X.Y.6]
     95   /// Tag to disengage optional objects.
     96   constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
     97 
     98   // [X.Y.7]
     99   /**
    100    *  @brief Exception class thrown when a disengaged optional object is
    101    *  dereferenced.
    102    *  @ingroup exceptions
    103    */
    104   class bad_optional_access : public logic_error
    105   {
    106   public:
    107     bad_optional_access() : logic_error("bad optional access") { }
    108 
    109     // XXX This constructor is non-standard. Should not be inline
    110     explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
    111 
    112     virtual ~bad_optional_access() noexcept = default;
    113   };
    114 
    115   /// @cond undocumented
    116 
    117   // XXX Does not belong here.
    118   [[noreturn]] inline void
    119   __throw_bad_optional_access(const char* __s)
    120   { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
    121 
    122   /**
    123     * @brief Class template that holds the necessary state for @ref optional
    124     * and that has the responsibility for construction and the special members.
    125     *
    126     * Such a separate base class template is necessary in order to
    127     * conditionally enable the special members (e.g. copy/move constructors).
    128     * Note that this means that @ref _Optional_base implements the
    129     * functionality for copy and move assignment, but not for converting
    130     * assignment.
    131     *
    132     * @see optional, _Enable_special_members
    133     */
    134   template<typename _Tp, bool _ShouldProvideDestructor =
    135 	   !is_trivially_destructible<_Tp>::value>
    136     class _Optional_base
    137     {
    138     private:
    139       // Remove const to avoid prohibition of reusing object storage for
    140       // const-qualified types in [3.8/9]. This is strictly internal
    141       // and even optional itself is oblivious to it.
    142       using _Stored_type = remove_const_t<_Tp>;
    143 
    144     public:
    145       // [X.Y.4.1] Constructors.
    146 
    147       // Constructors for disengaged optionals.
    148       constexpr _Optional_base() noexcept
    149       : _M_empty{} { }
    150 
    151       constexpr _Optional_base(nullopt_t) noexcept
    152       : _Optional_base{} { }
    153 
    154       // Constructors for engaged optionals.
    155       template<typename... _Args>
    156         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
    157         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
    158 
    159       template<typename _Up, typename... _Args,
    160                enable_if_t<is_constructible<_Tp,
    161                                             initializer_list<_Up>&,
    162                                             _Args&&...>::value,
    163                            int>...>
    164         constexpr explicit _Optional_base(in_place_t,
    165                                           initializer_list<_Up> __il,
    166                                           _Args&&... __args)
    167         : _M_payload(__il, std::forward<_Args>(__args)...),
    168           _M_engaged(true) { }
    169 
    170       // Copy and move constructors.
    171       _Optional_base(const _Optional_base& __other)
    172       {
    173         if (__other._M_engaged)
    174           this->_M_construct(__other._M_get());
    175       }
    176 
    177       _Optional_base(_Optional_base&& __other)
    178       noexcept(is_nothrow_move_constructible<_Tp>())
    179       {
    180         if (__other._M_engaged)
    181           this->_M_construct(std::move(__other._M_get()));
    182       }
    183 
    184       // [X.Y.4.3] (partly) Assignment.
    185       _Optional_base&
    186       operator=(const _Optional_base& __other)
    187       {
    188         if (this->_M_engaged && __other._M_engaged)
    189           this->_M_get() = __other._M_get();
    190         else
    191 	  {
    192 	    if (__other._M_engaged)
    193 	      this->_M_construct(__other._M_get());
    194 	    else
    195 	      this->_M_reset();
    196 	  }
    197 
    198         return *this;
    199       }
    200 
    201       _Optional_base&
    202       operator=(_Optional_base&& __other)
    203       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
    204 		      is_nothrow_move_assignable<_Tp>>())
    205       {
    206 	if (this->_M_engaged && __other._M_engaged)
    207 	  this->_M_get() = std::move(__other._M_get());
    208 	else
    209 	  {
    210 	    if (__other._M_engaged)
    211 	      this->_M_construct(std::move(__other._M_get()));
    212 	    else
    213 	      this->_M_reset();
    214 	  }
    215 	return *this;
    216       }
    217 
    218       // [X.Y.4.2] Destructor.
    219       ~_Optional_base()
    220       {
    221         if (this->_M_engaged)
    222           this->_M_payload.~_Stored_type();
    223       }
    224 
    225       // The following functionality is also needed by optional, hence the
    226       // protected accessibility.
    227     protected:
    228       constexpr bool _M_is_engaged() const noexcept
    229       { return this->_M_engaged; }
    230 
    231       // The _M_get operations have _M_engaged as a precondition.
    232       constexpr _Tp&
    233       _M_get() noexcept
    234       { return _M_payload; }
    235 
    236       constexpr const _Tp&
    237       _M_get() const noexcept
    238       { return _M_payload; }
    239 
    240       // The _M_construct operation has !_M_engaged as a precondition
    241       // while _M_destruct has _M_engaged as a precondition.
    242       template<typename... _Args>
    243         void
    244         _M_construct(_Args&&... __args)
    245         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
    246         {
    247           ::new (std::__addressof(this->_M_payload))
    248             _Stored_type(std::forward<_Args>(__args)...);
    249           this->_M_engaged = true;
    250         }
    251 
    252       void
    253       _M_destruct()
    254       {
    255         this->_M_engaged = false;
    256         this->_M_payload.~_Stored_type();
    257       }
    258 
    259       // _M_reset is a 'safe' operation with no precondition.
    260       void
    261       _M_reset()
    262       {
    263         if (this->_M_engaged)
    264           this->_M_destruct();
    265       }
    266 
    267     private:
    268       struct _Empty_byte { };
    269       union {
    270           _Empty_byte _M_empty;
    271           _Stored_type _M_payload;
    272       };
    273       bool _M_engaged = false;
    274     };
    275 
    276   /// Partial specialization that is exactly identical to the primary template
    277   /// save for not providing a destructor, to fulfill triviality requirements.
    278   template<typename _Tp>
    279     class _Optional_base<_Tp, false>
    280     {
    281     private:
    282       using _Stored_type = remove_const_t<_Tp>;
    283 
    284     public:
    285       constexpr _Optional_base() noexcept
    286       : _M_empty{} { }
    287 
    288       constexpr _Optional_base(nullopt_t) noexcept
    289       : _Optional_base{} { }
    290 
    291       template<typename... _Args>
    292         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
    293         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
    294 
    295       template<typename _Up, typename... _Args,
    296                enable_if_t<is_constructible<_Tp,
    297                                             initializer_list<_Up>&,
    298                                             _Args&&...>::value,
    299 			   int>...>
    300         constexpr explicit _Optional_base(in_place_t,
    301                                           initializer_list<_Up> __il,
    302                                           _Args&&... __args)
    303         : _M_payload(__il, std::forward<_Args>(__args)...),
    304           _M_engaged(true) { }
    305 
    306       _Optional_base(const _Optional_base& __other)
    307       {
    308         if (__other._M_engaged)
    309           this->_M_construct(__other._M_get());
    310       }
    311 
    312       _Optional_base(_Optional_base&& __other)
    313       noexcept(is_nothrow_move_constructible<_Tp>())
    314       {
    315         if (__other._M_engaged)
    316           this->_M_construct(std::move(__other._M_get()));
    317       }
    318 
    319       _Optional_base&
    320       operator=(const _Optional_base& __other)
    321       {
    322 	if (this->_M_engaged && __other._M_engaged)
    323 	  this->_M_get() = __other._M_get();
    324 	else
    325 	  {
    326 	    if (__other._M_engaged)
    327 	      this->_M_construct(__other._M_get());
    328 	    else
    329 	      this->_M_reset();
    330 	  }
    331 	return *this;
    332       }
    333 
    334       _Optional_base&
    335       operator=(_Optional_base&& __other)
    336       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
    337 		      is_nothrow_move_assignable<_Tp>>())
    338       {
    339 	if (this->_M_engaged && __other._M_engaged)
    340 	  this->_M_get() = std::move(__other._M_get());
    341 	else
    342 	  {
    343 	    if (__other._M_engaged)
    344 	      this->_M_construct(std::move(__other._M_get()));
    345 	    else
    346 	      this->_M_reset();
    347 	  }
    348 	return *this;
    349       }
    350 
    351       // Sole difference
    352       // ~_Optional_base() noexcept = default;
    353 
    354     protected:
    355       constexpr bool _M_is_engaged() const noexcept
    356       { return this->_M_engaged; }
    357 
    358       _Tp&
    359       _M_get() noexcept
    360       { return _M_payload; }
    361 
    362       constexpr const _Tp&
    363       _M_get() const noexcept
    364       { return _M_payload; }
    365 
    366       template<typename... _Args>
    367         void
    368         _M_construct(_Args&&... __args)
    369         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
    370         {
    371           ::new (std::__addressof(this->_M_payload))
    372             _Stored_type(std::forward<_Args>(__args)...);
    373           this->_M_engaged = true;
    374         }
    375 
    376       void
    377       _M_destruct()
    378       {
    379         this->_M_engaged = false;
    380         this->_M_payload.~_Stored_type();
    381       }
    382 
    383       void
    384       _M_reset()
    385       {
    386         if (this->_M_engaged)
    387           this->_M_destruct();
    388       }
    389 
    390     private:
    391       struct _Empty_byte { };
    392       union
    393       {
    394 	_Empty_byte _M_empty;
    395 	_Stored_type _M_payload;
    396       };
    397       bool _M_engaged = false;
    398     };
    399 
    400   template<typename _Tp, typename _Up>
    401     using __converts_from_optional =
    402       __or_<is_constructible<_Tp, const optional<_Up>&>,
    403 	    is_constructible<_Tp, optional<_Up>&>,
    404 	    is_constructible<_Tp, const optional<_Up>&&>,
    405 	    is_constructible<_Tp, optional<_Up>&&>,
    406 	    is_convertible<const optional<_Up>&, _Tp>,
    407 	    is_convertible<optional<_Up>&, _Tp>,
    408 	    is_convertible<const optional<_Up>&&, _Tp>,
    409 	    is_convertible<optional<_Up>&&, _Tp>>;
    410 
    411   template<typename _Tp, typename _Up>
    412     using __assigns_from_optional =
    413       __or_<is_assignable<_Tp&, const optional<_Up>&>,
    414 	    is_assignable<_Tp&, optional<_Up>&>,
    415 	    is_assignable<_Tp&, const optional<_Up>&&>,
    416 	    is_assignable<_Tp&, optional<_Up>&&>>;
    417 
    418   /// @endcond
    419 
    420   /**
    421     * @brief Class template for optional values.
    422     */
    423   template<typename _Tp>
    424     class optional
    425     : private _Optional_base<_Tp>,
    426       private _Enable_copy_move<
    427         // Copy constructor.
    428         is_copy_constructible<_Tp>::value,
    429         // Copy assignment.
    430         __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
    431         // Move constructor.
    432         is_move_constructible<_Tp>::value,
    433         // Move assignment.
    434         __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
    435         // Unique tag type.
    436         optional<_Tp>>
    437     {
    438       static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
    439 			   __not_<is_same<remove_cv_t<_Tp>, in_place_t>>,
    440 			   __not_<is_reference<_Tp>>>(),
    441                     "Invalid instantiation of optional<T>");
    442 
    443     private:
    444       using _Base = _Optional_base<_Tp>;
    445 
    446     public:
    447       using value_type = _Tp;
    448 
    449       // _Optional_base has the responsibility for construction.
    450       using _Base::_Base;
    451 
    452       constexpr optional() = default;
    453       // Converting constructors for engaged optionals.
    454       template <typename _Up = _Tp,
    455                 enable_if_t<__and_<
    456 			      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
    457 			      is_constructible<_Tp, _Up&&>,
    458 			      is_convertible<_Up&&, _Tp>
    459 			      >::value, bool> = true>
    460       constexpr optional(_Up&& __t)
    461         : _Base(in_place, std::forward<_Up>(__t)) { }
    462 
    463       template <typename _Up = _Tp,
    464                 enable_if_t<__and_<
    465 			      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
    466 			      is_constructible<_Tp, _Up&&>,
    467 			      __not_<is_convertible<_Up&&, _Tp>>
    468 			      >::value, bool> = false>
    469       explicit constexpr optional(_Up&& __t)
    470         : _Base(in_place, std::forward<_Up>(__t)) { }
    471 
    472       template <typename _Up,
    473                 enable_if_t<__and_<
    474 			    __not_<is_same<_Tp, _Up>>,
    475 			    is_constructible<_Tp, const _Up&>,
    476 			    is_convertible<const _Up&, _Tp>,
    477 			    __not_<__converts_from_optional<_Tp, _Up>>
    478 			    >::value, bool> = true>
    479       constexpr optional(const optional<_Up>& __t)
    480       {
    481 	if (__t)
    482 	  emplace(*__t);
    483       }
    484 
    485       template <typename _Up,
    486                  enable_if_t<__and_<
    487 			       __not_<is_same<_Tp, _Up>>,
    488 			       is_constructible<_Tp, const _Up&>,
    489 			       __not_<is_convertible<const _Up&, _Tp>>,
    490 			       __not_<__converts_from_optional<_Tp, _Up>>
    491 			       >::value, bool> = false>
    492       explicit constexpr optional(const optional<_Up>& __t)
    493       {
    494 	if (__t)
    495 	  emplace(*__t);
    496       }
    497 
    498       template <typename _Up,
    499                 enable_if_t<__and_<
    500 			      __not_<is_same<_Tp, _Up>>,
    501 			      is_constructible<_Tp, _Up&&>,
    502 			      is_convertible<_Up&&, _Tp>,
    503 			      __not_<__converts_from_optional<_Tp, _Up>>
    504 			      >::value, bool> = true>
    505       constexpr optional(optional<_Up>&& __t)
    506       {
    507 	if (__t)
    508 	  emplace(std::move(*__t));
    509       }
    510 
    511       template <typename _Up,
    512                 enable_if_t<__and_<
    513 			    __not_<is_same<_Tp, _Up>>,
    514 			    is_constructible<_Tp, _Up&&>,
    515 			    __not_<is_convertible<_Up&&, _Tp>>,
    516 			    __not_<__converts_from_optional<_Tp, _Up>>
    517 			    >::value, bool> = false>
    518       explicit constexpr optional(optional<_Up>&& __t)
    519       {
    520 	if (__t)
    521 	  emplace(std::move(*__t));
    522       }
    523 
    524       // [X.Y.4.3] (partly) Assignment.
    525       optional&
    526       operator=(nullopt_t) noexcept
    527       {
    528         this->_M_reset();
    529         return *this;
    530       }
    531 
    532       template<typename _Up = _Tp>
    533         enable_if_t<__and_<
    534 		      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
    535 		      is_constructible<_Tp, _Up>,
    536 		      __not_<__and_<is_scalar<_Tp>,
    537 				    is_same<_Tp, decay_t<_Up>>>>,
    538 		      is_assignable<_Tp&, _Up>>::value,
    539 		    optional&>
    540         operator=(_Up&& __u)
    541         {
    542           if (this->_M_is_engaged())
    543             this->_M_get() = std::forward<_Up>(__u);
    544           else
    545             this->_M_construct(std::forward<_Up>(__u));
    546 
    547           return *this;
    548         }
    549 
    550       template<typename _Up>
    551 	enable_if_t<__and_<
    552 		      __not_<is_same<_Tp, _Up>>,
    553 		      is_constructible<_Tp, const _Up&>,
    554 		      is_assignable<_Tp&, _Up>,
    555 		      __not_<__converts_from_optional<_Tp, _Up>>,
    556 		      __not_<__assigns_from_optional<_Tp, _Up>>
    557 		      >::value,
    558 		    optional&>
    559         operator=(const optional<_Up>& __u)
    560         {
    561           if (__u)
    562             {
    563               if (this->_M_is_engaged())
    564                 this->_M_get() = *__u;
    565               else
    566                 this->_M_construct(*__u);
    567             }
    568           else
    569             {
    570               this->_M_reset();
    571             }
    572           return *this;
    573         }
    574 
    575       template<typename _Up>
    576 	enable_if_t<__and_<
    577 		      __not_<is_same<_Tp, _Up>>,
    578 		      is_constructible<_Tp, _Up>,
    579 		      is_assignable<_Tp&, _Up>,
    580 		      __not_<__converts_from_optional<_Tp, _Up>>,
    581 		      __not_<__assigns_from_optional<_Tp, _Up>>
    582 		      >::value,
    583 		    optional&>
    584         operator=(optional<_Up>&& __u)
    585         {
    586           if (__u)
    587             {
    588               if (this->_M_is_engaged())
    589                 this->_M_get() = std::move(*__u);
    590               else
    591                 this->_M_construct(std::move(*__u));
    592             }
    593           else
    594             {
    595               this->_M_reset();
    596             }
    597 
    598           return *this;
    599         }
    600 
    601       template<typename... _Args>
    602 	enable_if_t<is_constructible<_Tp, _Args&&...>::value>
    603 	emplace(_Args&&... __args)
    604 	{
    605 	  this->_M_reset();
    606 	  this->_M_construct(std::forward<_Args>(__args)...);
    607 	}
    608 
    609       template<typename _Up, typename... _Args>
    610 	enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
    611 				     _Args&&...>::value>
    612 	emplace(initializer_list<_Up> __il, _Args&&... __args)
    613 	{
    614 	  this->_M_reset();
    615 	  this->_M_construct(__il, std::forward<_Args>(__args)...);
    616 	}
    617 
    618       // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
    619 
    620       // [X.Y.4.4] Swap.
    621       void
    622       swap(optional& __other)
    623       noexcept(is_nothrow_move_constructible<_Tp>()
    624                && __is_nothrow_swappable<_Tp>::value)
    625       {
    626         using std::swap;
    627 
    628         if (this->_M_is_engaged() && __other._M_is_engaged())
    629           swap(this->_M_get(), __other._M_get());
    630         else if (this->_M_is_engaged())
    631 	  {
    632 	    __other._M_construct(std::move(this->_M_get()));
    633 	    this->_M_destruct();
    634 	  }
    635         else if (__other._M_is_engaged())
    636 	  {
    637 	    this->_M_construct(std::move(__other._M_get()));
    638 	    __other._M_destruct();
    639 	  }
    640       }
    641 
    642       // [X.Y.4.5] Observers.
    643       constexpr const _Tp*
    644       operator->() const
    645       { return std::__addressof(this->_M_get()); }
    646 
    647       _Tp*
    648       operator->()
    649       { return std::__addressof(this->_M_get()); }
    650 
    651       constexpr const _Tp&
    652       operator*() const&
    653       { return this->_M_get(); }
    654 
    655       constexpr _Tp&
    656       operator*()&
    657       { return this->_M_get(); }
    658 
    659       constexpr _Tp&&
    660       operator*()&&
    661       { return std::move(this->_M_get()); }
    662 
    663       constexpr const _Tp&&
    664       operator*() const&&
    665       { return std::move(this->_M_get()); }
    666 
    667       constexpr explicit operator bool() const noexcept
    668       { return this->_M_is_engaged(); }
    669 
    670       constexpr const _Tp&
    671       value() const&
    672       {
    673 	if (this->_M_is_engaged())
    674 	  return this->_M_get();
    675 	__throw_bad_optional_access("Attempt to access value of a "
    676 				    "disengaged optional object");
    677       }
    678 
    679       constexpr _Tp&
    680       value()&
    681       {
    682 	if (this->_M_is_engaged())
    683 	  return this->_M_get();
    684 	__throw_bad_optional_access("Attempt to access value of a "
    685 				    "disengaged optional object");
    686       }
    687 
    688       constexpr _Tp&&
    689       value()&&
    690       {
    691 	if (this->_M_is_engaged())
    692 	  return std::move(this->_M_get());
    693 	__throw_bad_optional_access("Attempt to access value of a "
    694 				    "disengaged optional object");
    695       }
    696 
    697       constexpr const _Tp&&
    698       value() const&&
    699       {
    700 	if (this->_M_is_engaged())
    701 	  return std::move(this->_M_get());
    702 	__throw_bad_optional_access("Attempt to access value of a "
    703 				    "disengaged optional object");
    704       }
    705 
    706       template<typename _Up>
    707 	constexpr _Tp
    708 	value_or(_Up&& __u) const&
    709 	{
    710 	  static_assert(__and_<is_copy_constructible<_Tp>,
    711 			       is_convertible<_Up&&, _Tp>>(),
    712 			"Cannot return value");
    713 
    714 	  if (this->_M_is_engaged())
    715 	    return this->_M_get();
    716 	  else
    717 	    return static_cast<_Tp>(std::forward<_Up>(__u));
    718 	}
    719 
    720       template<typename _Up>
    721 	_Tp
    722 	value_or(_Up&& __u) &&
    723 	{
    724 	  static_assert(__and_<is_move_constructible<_Tp>,
    725 			       is_convertible<_Up&&, _Tp>>(),
    726 			"Cannot return value" );
    727 
    728 	  if (this->_M_is_engaged())
    729 	    return std::move(this->_M_get());
    730 	  else
    731 	    return static_cast<_Tp>(std::forward<_Up>(__u));
    732 	}
    733     };
    734 
    735   /// @relates experimental::optional @{
    736 
    737   // [X.Y.8] Comparisons between optional values.
    738   template<typename _Tp>
    739     constexpr bool
    740     operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
    741     {
    742       return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
    743 	     && (!__lhs || *__lhs == *__rhs);
    744     }
    745 
    746   template<typename _Tp>
    747     constexpr bool
    748     operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
    749     { return !(__lhs == __rhs); }
    750 
    751   template<typename _Tp>
    752     constexpr bool
    753     operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
    754     {
    755       return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
    756     }
    757 
    758   template<typename _Tp>
    759     constexpr bool
    760     operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
    761     { return __rhs < __lhs; }
    762 
    763   template<typename _Tp>
    764     constexpr bool
    765     operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
    766     { return !(__rhs < __lhs); }
    767 
    768   template<typename _Tp>
    769     constexpr bool
    770     operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
    771     { return !(__lhs < __rhs); }
    772 
    773   // [X.Y.9] Comparisons with nullopt.
    774   template<typename _Tp>
    775     constexpr bool
    776     operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
    777     { return !__lhs; }
    778 
    779   template<typename _Tp>
    780     constexpr bool
    781     operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
    782     { return !__rhs; }
    783 
    784   template<typename _Tp>
    785     constexpr bool
    786     operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
    787     { return static_cast<bool>(__lhs); }
    788 
    789   template<typename _Tp>
    790     constexpr bool
    791     operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
    792     { return static_cast<bool>(__rhs); }
    793 
    794   template<typename _Tp>
    795     constexpr bool
    796     operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
    797     { return false; }
    798 
    799   template<typename _Tp>
    800     constexpr bool
    801     operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
    802     { return static_cast<bool>(__rhs); }
    803 
    804   template<typename _Tp>
    805     constexpr bool
    806     operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
    807     { return static_cast<bool>(__lhs); }
    808 
    809   template<typename _Tp>
    810     constexpr bool
    811     operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
    812     { return false; }
    813 
    814   template<typename _Tp>
    815     constexpr bool
    816     operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
    817     { return !__lhs; }
    818 
    819   template<typename _Tp>
    820     constexpr bool
    821     operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
    822     { return true; }
    823 
    824   template<typename _Tp>
    825     constexpr bool
    826     operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
    827     { return true; }
    828 
    829   template<typename _Tp>
    830     constexpr bool
    831     operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
    832     { return !__rhs; }
    833 
    834   // [X.Y.10] Comparisons with value type.
    835   template<typename _Tp>
    836     constexpr bool
    837     operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
    838     { return __lhs && *__lhs == __rhs; }
    839 
    840   template<typename _Tp>
    841     constexpr bool
    842     operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
    843     { return __rhs && __lhs == *__rhs; }
    844 
    845   template<typename _Tp>
    846     constexpr bool
    847     operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
    848     { return !__lhs || !(*__lhs == __rhs); }
    849 
    850   template<typename _Tp>
    851     constexpr bool
    852     operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
    853     { return !__rhs || !(__lhs == *__rhs); }
    854 
    855   template<typename _Tp>
    856     constexpr bool
    857     operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
    858     { return !__lhs || *__lhs < __rhs; }
    859 
    860   template<typename _Tp>
    861     constexpr bool
    862     operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
    863     { return __rhs && __lhs < *__rhs; }
    864 
    865   template<typename _Tp>
    866     constexpr bool
    867     operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
    868     { return __lhs && __rhs < *__lhs; }
    869 
    870   template<typename _Tp>
    871     constexpr bool
    872     operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
    873     { return !__rhs || *__rhs < __lhs; }
    874 
    875   template<typename _Tp>
    876     constexpr bool
    877     operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
    878     { return !__lhs || !(__rhs < *__lhs); }
    879 
    880   template<typename _Tp>
    881     constexpr bool
    882     operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
    883     { return __rhs && !(*__rhs < __lhs); }
    884 
    885   template<typename _Tp>
    886     constexpr bool
    887     operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
    888     { return __lhs && !(*__lhs < __rhs); }
    889 
    890   template<typename _Tp>
    891     constexpr bool
    892     operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
    893     { return !__rhs || !(__lhs < *__rhs); }
    894 
    895   // [X.Y.11]
    896   template<typename _Tp>
    897     inline void
    898     swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
    899     noexcept(noexcept(__lhs.swap(__rhs)))
    900     { __lhs.swap(__rhs); }
    901 
    902   template<typename _Tp>
    903     constexpr optional<decay_t<_Tp>>
    904     make_optional(_Tp&& __t)
    905     { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
    906 
    907   /// @} relates experimental::optional
    908   /// @} group optional
    909 } // namespace fundamentals_v1
    910 } // namespace experimental
    911 
    912   // [X.Y.12]
    913   /// std::hash partial specialization for experimental::optional
    914   /// @relates experimental::optional
    915   template<typename _Tp>
    916     struct hash<experimental::optional<_Tp>>
    917     {
    918       using result_type = size_t;
    919       using argument_type = experimental::optional<_Tp>;
    920 
    921       size_t
    922       operator()(const experimental::optional<_Tp>& __t) const
    923       noexcept(noexcept(hash<_Tp> {}(*__t)))
    924       {
    925         // We pick an arbitrary hash for disengaged optionals which hopefully
    926         // usual values of _Tp won't typically hash to.
    927         constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
    928         return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
    929       }
    930     };
    931 
    932 _GLIBCXX_END_NAMESPACE_VERSION
    933 } // namespace std
    934 
    935 #endif // C++14
    936 
    937 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL
    938