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