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