Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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