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