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