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