libstdc++
optional
Go to the documentation of this file.
00001 // <optional> -*- C++ -*-
00002 
00003 // Copyright (C) 2013-2015 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file experimental/optional
00026  *  This is a TS C++ Library header.
00027  */
00028 
00029 #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
00030 #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
00031 
00032 /**
00033  * @defgroup experimental Experimental
00034  *
00035  * Components specified by various Technical Specifications.
00036  *
00037  * As indicated by the std::experimental namespace and the  header paths,
00038  * the contents of these Technical Specifications are experimental and not
00039  * part of the C++ standard. As such the interfaces and implementations may
00040  * change in the future, and there is <STRONG> no guarantee of compatibility
00041  * between different GCC releases </STRONG> for these features.
00042  */
00043 
00044 #if __cplusplus <= 201103L
00045 # include <bits/c++14_warning.h>
00046 #else
00047 
00048 #include <utility>
00049 #include <type_traits>
00050 #include <stdexcept>
00051 #include <new>
00052 #include <initializer_list>
00053 #include <bits/functexcept.h>
00054 #include <bits/functional_hash.h>
00055 #include <bits/enable_special_members.h>
00056 
00057 namespace std _GLIBCXX_VISIBILITY(default)
00058 {
00059 namespace experimental
00060 {
00061 inline namespace fundamentals_v1
00062 {
00063 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00064 
00065   /**
00066    * @defgroup optional Optional values
00067    * @ingroup experimental
00068    *
00069    * Class template for optional values and surrounding facilities, as
00070    * described in n3793 "A proposal to add a utility class to represent
00071    * optional objects (Revision 5)".
00072    *
00073    * @{
00074    */
00075 
00076 #define __cpp_lib_experimental_optional 201411
00077 
00078   // All subsequent [X.Y.n] references are against n3793.
00079 
00080   // [X.Y.4]
00081   template<typename _Tp>
00082     class optional;
00083 
00084   // [X.Y.5]
00085   /// Tag type for in-place construction.
00086   struct in_place_t { };
00087 
00088   /// Tag for in-place construction.
00089   constexpr in_place_t in_place { };
00090 
00091   // [X.Y.6]
00092   /// Tag type to disengage optional objects.
00093   struct nullopt_t
00094   {
00095     // Do not user-declare default constructor at all for
00096     // optional_value = {} syntax to work.
00097     // nullopt_t() = delete;
00098 
00099     // Used for constructing nullopt.
00100     enum class _Construct { _Token };
00101 
00102     // Must be constexpr for nullopt_t to be literal.
00103     explicit constexpr nullopt_t(_Construct) { }
00104   };
00105 
00106   // [X.Y.6]
00107   /// Tag to disengage optional objects.
00108   constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
00109 
00110   // [X.Y.7]
00111   /**
00112    *  @brief Exception class thrown when a disengaged optional object is
00113    *  dereferenced.
00114    *  @ingroup exceptions
00115    */
00116   class bad_optional_access : public logic_error
00117   {
00118   public:
00119     bad_optional_access() : logic_error("bad optional access") { }
00120 
00121     // XXX This constructor is non-standard. Should not be inline
00122     explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
00123 
00124     virtual ~bad_optional_access() noexcept = default;
00125   };
00126 
00127   void
00128   __throw_bad_optional_access(const char*)
00129   __attribute__((__noreturn__));
00130 
00131   // XXX Does not belong here.
00132   inline void
00133   __throw_bad_optional_access(const char* __s)
00134   { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
00135 
00136   template<typename _Tp, typename = void>
00137     struct _Has_addressof_mem : std::false_type { };
00138 
00139   template<typename _Tp>
00140     struct _Has_addressof_mem<_Tp,
00141          __void_t<decltype( std::declval<const _Tp&>().operator&() )>
00142       >
00143     : std::true_type { };
00144 
00145   template<typename _Tp, typename = void>
00146     struct _Has_addressof_free : std::false_type { };
00147 
00148   template<typename _Tp>
00149     struct _Has_addressof_free<_Tp,
00150          __void_t<decltype( operator&(std::declval<const _Tp&>()) )>
00151       >
00152     : std::true_type { };
00153 
00154   /**
00155     * @brief Trait that detects the presence of an overloaded unary operator&.
00156     *
00157     * Practically speaking this detects the presence of such an operator when
00158     * called on a const-qualified lvalue (i.e.
00159     * declval<_Tp * const&>().operator&()).
00160     */
00161   template<typename _Tp>
00162     struct _Has_addressof
00163     : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type
00164     { };
00165 
00166   /**
00167     * @brief An overload that attempts to take the address of an lvalue as a
00168     * constant expression. Falls back to __addressof in the presence of an
00169     * overloaded addressof operator (unary operator&), in which case the call
00170     * will not be a constant expression.
00171     */
00172   template<typename _Tp, enable_if_t<!_Has_addressof<_Tp>::value, int>...>
00173     constexpr _Tp* __constexpr_addressof(_Tp& __t)
00174     { return &__t; }
00175 
00176   /**
00177     * @brief Fallback overload that defers to __addressof.
00178     */
00179   template<typename _Tp, enable_if_t<_Has_addressof<_Tp>::value, int>...>
00180     inline _Tp* __constexpr_addressof(_Tp& __t)
00181     { return std::__addressof(__t); }
00182 
00183   /**
00184     * @brief Class template that holds the necessary state for @ref optional
00185     * and that has the responsibility for construction and the special members.
00186     *
00187     * Such a separate base class template is necessary in order to
00188     * conditionally enable the special members (e.g. copy/move constructors).
00189     * Note that this means that @ref _Optional_base implements the
00190     * functionality for copy and move assignment, but not for converting
00191     * assignment.
00192     *
00193     * @see optional, _Enable_special_members
00194     */
00195   template<typename _Tp, bool _ShouldProvideDestructor =
00196            !is_trivially_destructible<_Tp>::value>
00197     class _Optional_base
00198     {
00199     private:
00200       // Remove const to avoid prohibition of reusing object storage for
00201       // const-qualified types in [3.8/9]. This is strictly internal
00202       // and even optional itself is oblivious to it.
00203       using _Stored_type = remove_const_t<_Tp>;
00204 
00205     public:
00206       // [X.Y.4.1] Constructors.
00207 
00208       // Constructors for disengaged optionals.
00209       constexpr _Optional_base() noexcept
00210       : _M_empty{} { }
00211 
00212       constexpr _Optional_base(nullopt_t) noexcept
00213       : _Optional_base{} { }
00214 
00215       // Constructors for engaged optionals.
00216       constexpr _Optional_base(const _Tp& __t)
00217       : _M_payload(__t), _M_engaged(true) { }
00218 
00219       constexpr _Optional_base(_Tp&& __t)
00220       : _M_payload(std::move(__t)), _M_engaged(true) { }
00221 
00222       template<typename... _Args>
00223         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
00224         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
00225 
00226       template<typename _Up, typename... _Args,
00227                enable_if_t<is_constructible<_Tp,
00228                                             initializer_list<_Up>&,
00229                                             _Args&&...>::value,
00230                            int>...>
00231         constexpr explicit _Optional_base(in_place_t,
00232                                           initializer_list<_Up> __il,
00233                                           _Args&&... __args)
00234         : _M_payload(__il, std::forward<_Args>(__args)...),
00235           _M_engaged(true) { }
00236 
00237       // Copy and move constructors.
00238       _Optional_base(const _Optional_base& __other)
00239       {
00240         if (__other._M_engaged)
00241           this->_M_construct(__other._M_get());
00242       }
00243 
00244       _Optional_base(_Optional_base&& __other)
00245       noexcept(is_nothrow_move_constructible<_Tp>())
00246       {
00247         if (__other._M_engaged)
00248           this->_M_construct(std::move(__other._M_get()));
00249       }
00250 
00251       // [X.Y.4.3] (partly) Assignment.
00252       _Optional_base&
00253       operator=(const _Optional_base& __other)
00254       {
00255         if (this->_M_engaged && __other._M_engaged)
00256           this->_M_get() = __other._M_get();
00257         else
00258           {
00259             if (__other._M_engaged)
00260               this->_M_construct(__other._M_get());
00261             else
00262               this->_M_reset();
00263           }
00264 
00265         return *this;
00266       }
00267 
00268       _Optional_base&
00269       operator=(_Optional_base&& __other)
00270       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
00271                       is_nothrow_move_assignable<_Tp>>())
00272       {
00273         if (this->_M_engaged && __other._M_engaged)
00274           this->_M_get() = std::move(__other._M_get());
00275         else
00276           {
00277             if (__other._M_engaged)
00278               this->_M_construct(std::move(__other._M_get()));
00279             else
00280               this->_M_reset();
00281           }
00282         return *this;
00283       }
00284 
00285       // [X.Y.4.2] Destructor.
00286       ~_Optional_base()
00287       {
00288         if (this->_M_engaged)
00289           this->_M_payload.~_Stored_type();
00290       }
00291 
00292       // The following functionality is also needed by optional, hence the
00293       // protected accessibility.
00294     protected:
00295       constexpr bool _M_is_engaged() const noexcept
00296       { return this->_M_engaged; }
00297 
00298       // The _M_get operations have _M_engaged as a precondition.
00299       constexpr _Tp&
00300       _M_get() noexcept
00301       { return _M_payload; }
00302 
00303       constexpr const _Tp&
00304       _M_get() const noexcept
00305       { return _M_payload; }
00306 
00307       // The _M_construct operation has !_M_engaged as a precondition
00308       // while _M_destruct has _M_engaged as a precondition.
00309       template<typename... _Args>
00310         void
00311         _M_construct(_Args&&... __args)
00312         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
00313         {
00314           ::new (std::__addressof(this->_M_payload))
00315             _Stored_type(std::forward<_Args>(__args)...);
00316           this->_M_engaged = true;
00317         }
00318 
00319       void
00320       _M_destruct()
00321       {
00322         this->_M_engaged = false;
00323         this->_M_payload.~_Stored_type();
00324       }
00325 
00326       // _M_reset is a 'safe' operation with no precondition.
00327       void
00328       _M_reset()
00329       {
00330         if (this->_M_engaged)
00331           this->_M_destruct();
00332       }
00333 
00334     private:
00335       struct _Empty_byte { };
00336       union {
00337           _Empty_byte _M_empty;
00338           _Stored_type _M_payload;
00339       };
00340       bool _M_engaged = false;
00341     };
00342 
00343   /// Partial specialization that is exactly identical to the primary template
00344   /// save for not providing a destructor, to fulfill triviality requirements.
00345   template<typename _Tp>
00346     class _Optional_base<_Tp, false>
00347     {
00348     private:
00349       using _Stored_type = remove_const_t<_Tp>;
00350 
00351     public:
00352       constexpr _Optional_base() noexcept
00353       : _M_empty{} { }
00354 
00355       constexpr _Optional_base(nullopt_t) noexcept
00356       : _Optional_base{} { }
00357 
00358       constexpr _Optional_base(const _Tp& __t)
00359       : _M_payload(__t), _M_engaged(true) { }
00360 
00361       constexpr _Optional_base(_Tp&& __t)
00362       : _M_payload(std::move(__t)), _M_engaged(true) { }
00363 
00364       template<typename... _Args>
00365         constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
00366         : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
00367 
00368       template<typename _Up, typename... _Args,
00369                enable_if_t<is_constructible<_Tp,
00370                                             initializer_list<_Up>&,
00371                                             _Args&&...>::value,
00372                            int>...>
00373         constexpr explicit _Optional_base(in_place_t,
00374                                           initializer_list<_Up> __il,
00375                                           _Args&&... __args)
00376         : _M_payload(__il, std::forward<_Args>(__args)...),
00377           _M_engaged(true) { }
00378 
00379       _Optional_base(const _Optional_base& __other)
00380       {
00381         if (__other._M_engaged)
00382           this->_M_construct(__other._M_get());
00383       }
00384 
00385       _Optional_base(_Optional_base&& __other)
00386       noexcept(is_nothrow_move_constructible<_Tp>())
00387       {
00388         if (__other._M_engaged)
00389           this->_M_construct(std::move(__other._M_get()));
00390       }
00391 
00392       _Optional_base&
00393       operator=(const _Optional_base& __other)
00394       {
00395         if (this->_M_engaged && __other._M_engaged)
00396           this->_M_get() = __other._M_get();
00397         else
00398           {
00399             if (__other._M_engaged)
00400               this->_M_construct(__other._M_get());
00401             else
00402               this->_M_reset();
00403           }
00404         return *this;
00405       }
00406 
00407       _Optional_base&
00408       operator=(_Optional_base&& __other)
00409       noexcept(__and_<is_nothrow_move_constructible<_Tp>,
00410                       is_nothrow_move_assignable<_Tp>>())
00411       {
00412         if (this->_M_engaged && __other._M_engaged)
00413           this->_M_get() = std::move(__other._M_get());
00414         else
00415           {
00416             if (__other._M_engaged)
00417               this->_M_construct(std::move(__other._M_get()));
00418             else
00419               this->_M_reset();
00420           }
00421         return *this;
00422       }
00423 
00424       // Sole difference
00425       // ~_Optional_base() noexcept = default;
00426 
00427     protected:
00428       constexpr bool _M_is_engaged() const noexcept
00429       { return this->_M_engaged; }
00430 
00431       _Tp&
00432       _M_get() noexcept
00433       { return _M_payload; }
00434 
00435       constexpr const _Tp&
00436       _M_get() const noexcept
00437       { return _M_payload; }
00438 
00439       template<typename... _Args>
00440         void
00441         _M_construct(_Args&&... __args)
00442         noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
00443         {
00444           ::new (std::__addressof(this->_M_payload))
00445             _Stored_type(std::forward<_Args>(__args)...);
00446           this->_M_engaged = true;
00447         }
00448 
00449       void
00450       _M_destruct()
00451       {
00452         this->_M_engaged = false;
00453         this->_M_payload.~_Stored_type();
00454       }
00455 
00456       void
00457       _M_reset()
00458       {
00459         if (this->_M_engaged)
00460           this->_M_destruct();
00461       }
00462 
00463     private:
00464       struct _Empty_byte { };
00465       union
00466       {
00467         _Empty_byte _M_empty;
00468         _Stored_type _M_payload;
00469       };
00470       bool _M_engaged = false;
00471     };
00472 
00473   /**
00474     * @brief Class template for optional values.
00475     */
00476   template<typename _Tp>
00477     class optional
00478     : private _Optional_base<_Tp>,
00479       private _Enable_copy_move<
00480         // Copy constructor.
00481         is_copy_constructible<_Tp>::value,
00482         // Copy assignment.
00483         __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
00484         // Move constructor.
00485         is_move_constructible<_Tp>::value,
00486         // Move assignment.
00487         __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
00488         // Unique tag type.
00489         optional<_Tp>>
00490     {
00491       static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
00492                            __not_<is_same<remove_cv_t<_Tp>, in_place_t>>,
00493                            __not_<is_reference<_Tp>>>(),
00494                     "Invalid instantiation of optional<T>");
00495 
00496     private:
00497       using _Base = _Optional_base<_Tp>;
00498 
00499     public:
00500       using value_type = _Tp;
00501 
00502       // _Optional_base has the responsibility for construction.
00503       using _Base::_Base;
00504 
00505       // [X.Y.4.3] (partly) Assignment.
00506       optional&
00507       operator=(nullopt_t) noexcept
00508       {
00509         this->_M_reset();
00510         return *this;
00511       }
00512 
00513       template<typename _Up>
00514         enable_if_t<is_same<_Tp, decay_t<_Up>>::value, optional&>
00515         operator=(_Up&& __u)
00516         {
00517           static_assert(__and_<is_constructible<_Tp, _Up>,
00518                                is_assignable<_Tp&, _Up>>(),
00519                         "Cannot assign to value type from argument");
00520 
00521           if (this->_M_is_engaged())
00522             this->_M_get() = std::forward<_Up>(__u);
00523           else
00524             this->_M_construct(std::forward<_Up>(__u));
00525 
00526           return *this;
00527         }
00528 
00529       template<typename... _Args>
00530         void
00531         emplace(_Args&&... __args)
00532         {
00533           static_assert(is_constructible<_Tp, _Args&&...>(),
00534                         "Cannot emplace value type from arguments");
00535 
00536           this->_M_reset();
00537           this->_M_construct(std::forward<_Args>(__args)...);
00538         }
00539 
00540       template<typename _Up, typename... _Args>
00541         enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
00542                                      _Args&&...>::value>
00543         emplace(initializer_list<_Up> __il, _Args&&... __args)
00544         {
00545           this->_M_reset();
00546           this->_M_construct(__il, std::forward<_Args>(__args)...);
00547         }
00548 
00549       // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
00550 
00551       // [X.Y.4.4] Swap.
00552       void
00553       swap(optional& __other)
00554       noexcept(is_nothrow_move_constructible<_Tp>()
00555                && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
00556       {
00557         using std::swap;
00558 
00559         if (this->_M_is_engaged() && __other._M_is_engaged())
00560           swap(this->_M_get(), __other._M_get());
00561         else if (this->_M_is_engaged())
00562           {
00563             __other._M_construct(std::move(this->_M_get()));
00564             this->_M_destruct();
00565           }
00566         else if (__other._M_is_engaged())
00567           {
00568             this->_M_construct(std::move(__other._M_get()));
00569             __other._M_destruct();
00570           }
00571       }
00572 
00573       // [X.Y.4.5] Observers.
00574       constexpr const _Tp*
00575       operator->() const
00576       { return __constexpr_addressof(this->_M_get()); }
00577 
00578       _Tp*
00579       operator->()
00580       { return std::__addressof(this->_M_get()); }
00581 
00582       constexpr const _Tp&
00583       operator*() const&
00584       { return this->_M_get(); }
00585 
00586       constexpr _Tp&
00587       operator*()&
00588       { return this->_M_get(); }
00589 
00590       constexpr _Tp&&
00591       operator*()&&
00592       { return std::move(this->_M_get()); }
00593 
00594       constexpr const _Tp&&
00595       operator*() const&&
00596       { return std::move(this->_M_get()); }
00597 
00598       constexpr explicit operator bool() const noexcept
00599       { return this->_M_is_engaged(); }
00600 
00601       constexpr const _Tp&
00602       value() const&
00603       {
00604         return this->_M_is_engaged()
00605           ?  this->_M_get()
00606           : (__throw_bad_optional_access("Attempt to access value of a "
00607                                          "disengaged optional object"),
00608              this->_M_get());
00609       }
00610 
00611       constexpr _Tp&
00612       value()&
00613       {
00614         return this->_M_is_engaged()
00615           ?  this->_M_get()
00616           : (__throw_bad_optional_access("Attempt to access value of a "
00617                                          "disengaged optional object"),
00618              this->_M_get());
00619       }
00620 
00621       constexpr _Tp&&
00622       value()&&
00623       {
00624         return this->_M_is_engaged()
00625           ?  std::move(this->_M_get())
00626           : (__throw_bad_optional_access("Attempt to access value of a "
00627                                          "disengaged optional object"),
00628              std::move(this->_M_get()));
00629       }
00630 
00631       constexpr const _Tp&&
00632       value() const&&
00633       {
00634         return this->_M_is_engaged()
00635           ?  std::move(this->_M_get())
00636           : (__throw_bad_optional_access("Attempt to access value of a "
00637                                          "disengaged optional object"),
00638              std::move(this->_M_get()));
00639       }
00640 
00641       template<typename _Up>
00642         constexpr _Tp
00643         value_or(_Up&& __u) const&
00644         {
00645           static_assert(__and_<is_copy_constructible<_Tp>,
00646                                is_convertible<_Up&&, _Tp>>(),
00647                         "Cannot return value");
00648 
00649           return this->_M_is_engaged()
00650             ? this->_M_get()
00651             : static_cast<_Tp>(std::forward<_Up>(__u));
00652         }
00653 
00654       template<typename _Up>
00655         _Tp
00656         value_or(_Up&& __u) &&
00657         {
00658           static_assert(__and_<is_move_constructible<_Tp>,
00659                                is_convertible<_Up&&, _Tp>>(),
00660                         "Cannot return value" );
00661 
00662           return this->_M_is_engaged()
00663             ? std::move(this->_M_get())
00664             : static_cast<_Tp>(std::forward<_Up>(__u));
00665         }
00666     };
00667 
00668   // [X.Y.8] Comparisons between optional values.
00669   template<typename _Tp>
00670     constexpr bool
00671     operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
00672     {
00673       return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
00674              && (!__lhs || *__lhs == *__rhs);
00675     }
00676 
00677   template<typename _Tp>
00678     constexpr bool
00679     operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
00680     { return !(__lhs == __rhs); }
00681 
00682   template<typename _Tp>
00683     constexpr bool
00684     operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
00685     {
00686       return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
00687     }
00688 
00689   template<typename _Tp>
00690     constexpr bool
00691     operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
00692     { return __rhs < __lhs; }
00693 
00694   template<typename _Tp>
00695     constexpr bool
00696     operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
00697     { return !(__rhs < __lhs); }
00698 
00699   template<typename _Tp>
00700     constexpr bool
00701     operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
00702     { return !(__lhs < __rhs); }
00703 
00704   // [X.Y.9] Comparisons with nullopt.
00705   template<typename _Tp>
00706     constexpr bool
00707     operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
00708     { return !__lhs; }
00709 
00710   template<typename _Tp>
00711     constexpr bool
00712     operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
00713     { return !__rhs; }
00714 
00715   template<typename _Tp>
00716     constexpr bool
00717     operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
00718     { return static_cast<bool>(__lhs); }
00719 
00720   template<typename _Tp>
00721     constexpr bool
00722     operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
00723     { return static_cast<bool>(__rhs); }
00724 
00725   template<typename _Tp>
00726     constexpr bool
00727     operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
00728     { return false; }
00729 
00730   template<typename _Tp>
00731     constexpr bool
00732     operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
00733     { return static_cast<bool>(__rhs); }
00734 
00735   template<typename _Tp>
00736     constexpr bool
00737     operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
00738     { return static_cast<bool>(__lhs); }
00739 
00740   template<typename _Tp>
00741     constexpr bool
00742     operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
00743     { return false; }
00744 
00745   template<typename _Tp>
00746     constexpr bool
00747     operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
00748     { return !__lhs; }
00749 
00750   template<typename _Tp>
00751     constexpr bool
00752     operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
00753     { return true; }
00754 
00755   template<typename _Tp>
00756     constexpr bool
00757     operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
00758     { return true; }
00759 
00760   template<typename _Tp>
00761     constexpr bool
00762     operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
00763     { return !__rhs; }
00764 
00765   // [X.Y.10] Comparisons with value type.
00766   template<typename _Tp>
00767     constexpr bool
00768     operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
00769     { return __lhs && *__lhs == __rhs; }
00770 
00771   template<typename _Tp>
00772     constexpr bool
00773     operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
00774     { return __rhs && __lhs == *__rhs; }
00775 
00776   template<typename _Tp>
00777     constexpr bool
00778     operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
00779     { return !__lhs || !(*__lhs == __rhs); }
00780 
00781   template<typename _Tp>
00782     constexpr bool
00783     operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
00784     { return !__rhs || !(__lhs == *__rhs); }
00785 
00786   template<typename _Tp>
00787     constexpr bool
00788     operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
00789     { return !__lhs || *__lhs < __rhs; }
00790 
00791   template<typename _Tp>
00792     constexpr bool
00793     operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
00794     { return __rhs && __lhs < *__rhs; }
00795 
00796   template<typename _Tp>
00797     constexpr bool
00798     operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
00799     { return __lhs && __rhs < *__lhs; }
00800 
00801   template<typename _Tp>
00802     constexpr bool
00803     operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
00804     { return !__rhs || *__rhs < __lhs; }
00805 
00806   template<typename _Tp>
00807     constexpr bool
00808     operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
00809     { return !__lhs || !(__rhs < *__lhs); }
00810 
00811   template<typename _Tp>
00812     constexpr bool
00813     operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
00814     { return __rhs && !(*__rhs < __lhs); }
00815 
00816   template<typename _Tp>
00817     constexpr bool
00818     operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
00819     { return __lhs && !(*__lhs < __rhs); }
00820 
00821   template<typename _Tp>
00822     constexpr bool
00823     operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
00824     { return !__rhs || !(__lhs < *__rhs); }
00825 
00826   // [X.Y.11]
00827   template<typename _Tp>
00828     inline void
00829     swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
00830     noexcept(noexcept(__lhs.swap(__rhs)))
00831     { __lhs.swap(__rhs); }
00832 
00833   template<typename _Tp>
00834     constexpr optional<decay_t<_Tp>>
00835     make_optional(_Tp&& __t)
00836     { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
00837 
00838   // @} group optional
00839 _GLIBCXX_END_NAMESPACE_VERSION
00840 } // namespace fundamentals_v1
00841 }
00842 
00843   // [X.Y.12]
00844   template<typename _Tp>
00845     struct hash<experimental::optional<_Tp>>
00846     {
00847       using result_type = size_t;
00848       using argument_type = experimental::optional<_Tp>;
00849 
00850       size_t
00851       operator()(const experimental::optional<_Tp>& __t) const
00852       noexcept(noexcept(hash<_Tp> {}(*__t)))
00853       {
00854         // We pick an arbitrary hash for disengaged optionals which hopefully
00855         // usual values of _Tp won't typically hash to.
00856         constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
00857         return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
00858       }
00859     };
00860 }
00861 
00862 #endif // C++14
00863 
00864 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL