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