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