aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libstdc++-v3/include/experimental/optional
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libstdc++-v3/include/experimental/optional')
-rw-r--r--gcc-4.9/libstdc++-v3/include/experimental/optional823
1 files changed, 823 insertions, 0 deletions
diff --git a/gcc-4.9/libstdc++-v3/include/experimental/optional b/gcc-4.9/libstdc++-v3/include/experimental/optional
new file mode 100644
index 0000000..5f2d93f
--- /dev/null
+++ b/gcc-4.9/libstdc++-v3/include/experimental/optional
@@ -0,0 +1,823 @@
+// <optional> -*- C++ -*-
+
+// Copyright (C) 2013-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file experimental/optional
+ * This is a TS C++ Library header.
+ */
+
+#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
+#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
+
+/**
+ * @defgroup experimental Experimental
+ *
+ * Components specified by various Technical Specifications.
+ */
+
+#if __cplusplus <= 201103L
+# include <bits/c++14_warning.h>
+#else
+
+#include <utility>
+#include <type_traits>
+#include <stdexcept>
+#include <new>
+#include <initializer_list>
+#include <bits/functexcept.h>
+#include <bits/functional_hash.h>
+#include <bits/enable_special_members.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace experimental
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @defgroup optional Optional values
+ * @ingroup experimental
+ *
+ * Class template for optional values and surrounding facilities, as
+ * described in n3793 "A proposal to add a utility class to represent
+ * optional objects (Revision 5)".
+ *
+ * @{
+ */
+
+ // All subsequent [X.Y.n] references are against n3793.
+
+ // [X.Y.4]
+ template<typename _Tp>
+ class optional;
+
+ // [X.Y.5]
+ /// Tag type for in-place construction.
+ struct in_place_t { };
+
+ /// Tag for in-place construction.
+ constexpr in_place_t in_place { };
+
+ // [X.Y.6]
+ /// Tag type to disengage optional objects.
+ struct nullopt_t
+ {
+ // Do not user-declare default constructor at all for
+ // optional_value = {} syntax to work.
+ // nullopt_t() = delete;
+
+ // Used for constructing nullopt.
+ enum class _Construct { _Token };
+
+ // Must be constexpr for nullopt_t to be literal.
+ explicit constexpr nullopt_t(_Construct) { }
+ };
+
+ // [X.Y.6]
+ /// Tag to disengage optional objects.
+ constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
+
+ // [X.Y.7]
+ /**
+ * @brief Exception class thrown when a disengaged optional object is
+ * dereferenced.
+ * @ingroup exceptions
+ */
+ class bad_optional_access : public logic_error
+ {
+ public:
+ // XXX Should not be inline
+ explicit bad_optional_access(const string& __arg) : logic_error(__arg) { }
+
+ explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
+
+ virtual ~bad_optional_access() noexcept = default;
+ };
+
+ void
+ __throw_bad_optional_access(const char*)
+ __attribute__((__noreturn__));
+
+ // XXX Does not belong here.
+ inline void
+ __throw_bad_optional_access(const char* __s)
+ { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
+
+ template<typename _Tp, typename _Sfinae = void>
+ struct _Has_addressof_impl : std::false_type { };
+
+ template<typename _Tp>
+ struct _Has_addressof_impl<_Tp,
+ decltype( std::declval<const _Tp&>().operator&(), void() )>
+ : std::true_type { };
+
+ /**
+ * @brief Trait that detects the presence of an overloaded unary operator&.
+ *
+ * Practically speaking this detects the presence of such an operator when
+ * called on a const-qualified lvalue (i.e.
+ * declval<_Tp * const&>().operator&()).
+ */
+ template<typename _Tp>
+ struct _Has_addressof : _Has_addressof_impl<_Tp>::type { };
+
+ /**
+ * @brief An overload that attempts to take the address of an lvalue as a
+ * constant expression. Falls back to __addressof in the presence of an
+ * overloaded addressof operator (unary operator&), in which case the call
+ * will not be a constant expression.
+ */
+ template<typename _Tp, typename enable_if<!_Has_addressof<_Tp>::value,
+ int>::type...>
+ constexpr _Tp* __constexpr_addressof(_Tp& __t)
+ { return &__t; }
+
+ /**
+ * @brief Fallback overload that defers to __addressof.
+ */
+ template<typename _Tp, typename enable_if<_Has_addressof<_Tp>::value,
+ int>::type...>
+ inline _Tp* __constexpr_addressof(_Tp& __t)
+ { return std::__addressof(__t); }
+
+ /**
+ * @brief Class template that holds the necessary state for @ref optional
+ * and that has the responsibility for construction and the special members.
+ *
+ * Such a separate base class template is necessary in order to
+ * conditionally enable the special members (e.g. copy/move constructors).
+ * Note that this means that @ref _Optional_base implements the
+ * functionality for copy and move assignment, but not for converting
+ * assignment.
+ *
+ * @see optional, _Enable_special_members
+ */
+ template<typename _Tp, bool _ShouldProvideDestructor =
+ !is_trivially_destructible<_Tp>::value>
+ class _Optional_base
+ {
+ private:
+ // Remove const to avoid prohibition of reusing object storage for
+ // const-qualified types in [3.8/9]. This is strictly internal
+ // and even optional itself is oblivious to it.
+ using _Stored_type = typename remove_const<_Tp>::type;
+
+ public:
+ // [X.Y.4.1] Constructors.
+
+ // Constructors for disengaged optionals.
+ constexpr _Optional_base() noexcept
+ : _M_empty{} { }
+
+ constexpr _Optional_base(nullopt_t) noexcept
+ : _Optional_base{} { }
+
+ // Constructors for engaged optionals.
+ constexpr _Optional_base(const _Tp& __t)
+ : _M_payload(__t), _M_engaged(true) { }
+
+ constexpr _Optional_base(_Tp&& __t)
+ : _M_payload(std::move(__t)), _M_engaged(true) { }
+
+ template<typename... _Args>
+ constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
+ : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
+
+ template<typename _Up, typename... _Args,
+ typename enable_if<is_constructible<_Tp,
+ initializer_list<_Up>&,
+ _Args&&...>::value,
+ int>::type...>
+ constexpr explicit _Optional_base(in_place_t,
+ initializer_list<_Up> __il,
+ _Args&&... __args)
+ : _M_payload(__il, std::forward<_Args>(__args)...),
+ _M_engaged(true) { }
+
+ // Copy and move constructors.
+ _Optional_base(const _Optional_base& __other)
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ }
+
+ _Optional_base(_Optional_base&& __other)
+ noexcept(is_nothrow_move_constructible<_Tp>())
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ }
+
+ // [X.Y.4.3] (partly) Assignment.
+ _Optional_base&
+ operator=(const _Optional_base& __other)
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = __other._M_get();
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ else
+ this->_M_reset();
+ }
+
+ return *this;
+ }
+
+ _Optional_base&
+ operator=(_Optional_base&& __other)
+ noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+ is_nothrow_move_assignable<_Tp>>())
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = std::move(__other._M_get());
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ else
+ this->_M_reset();
+ }
+ return *this;
+ }
+
+ // [X.Y.4.2] Destructor.
+ ~_Optional_base()
+ {
+ if (this->_M_engaged)
+ this->_M_payload.~_Stored_type();
+ }
+
+ // The following functionality is also needed by optional, hence the
+ // protected accessibility.
+ protected:
+ constexpr bool _M_is_engaged() const noexcept
+ { return this->_M_engaged; }
+
+ // The _M_get operations have _M_engaged as a precondition.
+ _Tp&
+ _M_get() noexcept
+ { return _M_payload; }
+
+ constexpr const _Tp&
+ _M_get() const noexcept
+ { return _M_payload; }
+
+ // The _M_construct operation has !_M_engaged as a precondition
+ // while _M_destruct has _M_engaged as a precondition.
+ template<typename... _Args>
+ void
+ _M_construct(_Args&&... __args)
+ noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
+ {
+ ::new (std::__addressof(this->_M_payload))
+ _Stored_type(std::forward<_Args>(__args)...);
+ this->_M_engaged = true;
+ }
+
+ void
+ _M_destruct()
+ {
+ this->_M_engaged = false;
+ this->_M_payload.~_Stored_type();
+ }
+
+ // _M_reset is a 'safe' operation with no precondition.
+ void
+ _M_reset()
+ {
+ if (this->_M_engaged)
+ this->_M_destruct();
+ }
+
+ private:
+ struct _Empty_byte { };
+ union {
+ _Empty_byte _M_empty;
+ _Stored_type _M_payload;
+ };
+ bool _M_engaged = false;
+ };
+
+ /// Partial specialization that is exactly identical to the primary template
+ /// save for not providing a destructor, to fulfill triviality requirements.
+ template<typename _Tp>
+ class _Optional_base<_Tp, false>
+ {
+ private:
+ using _Stored_type = typename remove_const<_Tp>::type;
+
+ public:
+ constexpr _Optional_base() noexcept
+ : _M_empty{} { }
+
+ constexpr _Optional_base(nullopt_t) noexcept
+ : _Optional_base{} { }
+
+ constexpr _Optional_base(const _Tp& __t)
+ : _M_payload(__t), _M_engaged(true) { }
+
+ constexpr _Optional_base(_Tp&& __t)
+ : _M_payload(std::move(__t)), _M_engaged(true) { }
+
+ template<typename... _Args>
+ constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
+ : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
+
+ template<typename _Up, typename... _Args,
+ typename enable_if<is_constructible<_Tp,
+ initializer_list<_Up>&,
+ _Args&&...>::value,
+ int>::type...>
+ constexpr explicit _Optional_base(in_place_t,
+ initializer_list<_Up> __il,
+ _Args&&... __args)
+ : _M_payload(__il, std::forward<_Args>(__args)...),
+ _M_engaged(true) { }
+
+ _Optional_base(const _Optional_base& __other)
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ }
+
+ _Optional_base(_Optional_base&& __other)
+ noexcept(is_nothrow_move_constructible<_Tp>())
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ }
+
+ _Optional_base&
+ operator=(const _Optional_base& __other)
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = __other._M_get();
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ else
+ this->_M_reset();
+ }
+ return *this;
+ }
+
+ _Optional_base&
+ operator=(_Optional_base&& __other)
+ noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+ is_nothrow_move_assignable<_Tp>>())
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = std::move(__other._M_get());
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ else
+ this->_M_reset();
+ }
+ return *this;
+ }
+
+ // Sole difference
+ // ~_Optional_base() noexcept = default;
+
+ protected:
+ constexpr bool _M_is_engaged() const noexcept
+ { return this->_M_engaged; }
+
+ _Tp&
+ _M_get() noexcept
+ { return _M_payload; }
+
+ constexpr const _Tp&
+ _M_get() const noexcept
+ { return _M_payload; }
+
+ template<typename... _Args>
+ void
+ _M_construct(_Args&&... __args)
+ noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
+ {
+ ::new (std::__addressof(this->_M_payload))
+ _Stored_type(std::forward<_Args>(__args)...);
+ this->_M_engaged = true;
+ }
+
+ void
+ _M_destruct()
+ {
+ this->_M_engaged = false;
+ this->_M_payload.~_Stored_type();
+ }
+
+ void
+ _M_reset()
+ {
+ if (this->_M_engaged)
+ this->_M_destruct();
+ }
+
+ private:
+ struct _Empty_byte { };
+ union
+ {
+ _Empty_byte _M_empty;
+ _Stored_type _M_payload;
+ };
+ bool _M_engaged = false;
+ };
+
+ /**
+ * @brief Class template for optional values.
+ */
+ template<typename _Tp>
+ class optional
+ : private _Optional_base<_Tp>,
+ private _Enable_copy_move<
+ // Copy constructor.
+ is_copy_constructible<_Tp>::value,
+ // Copy assignment.
+ __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
+ // Move constructor.
+ is_move_constructible<_Tp>::value,
+ // Move assignment.
+ __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
+ // Unique tag type.
+ optional<_Tp>>
+ {
+ static_assert(__and_<__not_<is_same<typename remove_cv<_Tp>::type,
+ nullopt_t>>,
+ __not_<is_same<typename remove_cv<_Tp>::type,
+ in_place_t>>,
+ __not_<is_reference<_Tp>>>(),
+ "Invalid instantiation of optional<T>");
+
+ private:
+ using _Base = _Optional_base<_Tp>;
+
+ public:
+ using value_type = _Tp;
+
+ // _Optional_base has the responsibility for construction.
+ using _Base::_Base;
+
+ // [X.Y.4.3] (partly) Assignment.
+ optional&
+ operator=(nullopt_t) noexcept
+ {
+ this->_M_reset();
+ return *this;
+ }
+
+ template<typename _Up>
+ typename enable_if<
+ is_same<_Tp, typename decay<_Up>::type>::value,
+ optional&
+ >::type
+ operator=(_Up&& __u)
+ {
+ static_assert(__and_<is_constructible<_Tp, _Up>,
+ is_assignable<_Tp&, _Up>>(),
+ "Cannot assign to value type from argument");
+
+ if (this->_M_is_engaged())
+ this->_M_get() = std::forward<_Up>(__u);
+ else
+ this->_M_construct(std::forward<_Up>(__u));
+
+ return *this;
+ }
+
+ template<typename... _Args>
+ void
+ emplace(_Args&&... __args)
+ {
+ static_assert(is_constructible<_Tp, _Args&&...>(),
+ "Cannot emplace value type from arguments");
+
+ this->_M_reset();
+ this->_M_construct(std::forward<_Args>(__args)...);
+ }
+
+ template<typename _Up, typename... _Args>
+ typename enable_if<
+ is_constructible<_Tp,
+ initializer_list<_Up>&,
+ _Args&&...>::value
+ >::type
+ emplace(initializer_list<_Up> __il, _Args&&... __args)
+ {
+ this->_M_reset();
+ this->_M_construct(__il, std::forward<_Args>(__args)...);
+ }
+
+ // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
+
+ // [X.Y.4.4] Swap.
+ void
+ swap(optional& __other)
+ noexcept(is_nothrow_move_constructible<_Tp>()
+ && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
+ {
+ using std::swap;
+
+ if (this->_M_is_engaged() && __other._M_is_engaged())
+ swap(this->_M_get(), __other._M_get());
+ else if (this->_M_is_engaged())
+ {
+ __other._M_construct(std::move(this->_M_get()));
+ this->_M_destruct();
+ }
+ else if (__other._M_is_engaged())
+ {
+ this->_M_construct(std::move(__other._M_get()));
+ __other._M_destruct();
+ }
+ }
+
+ // [X.Y.4.5] Observers.
+ constexpr const _Tp*
+ operator->() const
+ { return __constexpr_addressof(this->_M_get()); }
+
+ _Tp*
+ operator->()
+ { return std::__addressof(this->_M_get()); }
+
+ constexpr const _Tp&
+ operator*() const
+ { return this->_M_get(); }
+
+ _Tp&
+ operator*()
+ { return this->_M_get(); }
+
+ constexpr explicit operator bool() const noexcept
+ { return this->_M_is_engaged(); }
+
+ constexpr const _Tp&
+ value() const
+ {
+ return this->_M_is_engaged()
+ ? this->_M_get()
+ : (__throw_bad_optional_access("Attempt to access value of a "
+ "disengaged optional object"),
+ this->_M_get());
+ }
+
+ _Tp&
+ value()
+ {
+ if (this->_M_is_engaged())
+ return this->_M_get();
+
+ __throw_bad_optional_access("Attempt to access value of a "
+ "disengaged optional object");
+ }
+
+ template<typename _Up>
+ constexpr _Tp
+ value_or(_Up&& __u) const&
+ {
+ static_assert(__and_<is_copy_constructible<_Tp>,
+ is_convertible<_Up&&, _Tp>>(),
+ "Cannot return value");
+
+ return this->_M_is_engaged()
+ ? this->_M_get()
+ : static_cast<_Tp>(std::forward<_Up>(__u));
+ }
+
+ template<typename _Up>
+ _Tp
+ value_or(_Up&& __u) &&
+ {
+ static_assert(__and_<is_move_constructible<_Tp>,
+ is_convertible<_Up&&, _Tp>>(),
+ "Cannot return value" );
+
+ return this->_M_is_engaged()
+ ? std::move(this->_M_get())
+ : static_cast<_Tp>(std::forward<_Up>(__u));
+ }
+ };
+
+ // [X.Y.8] Comparisons between optional values.
+ template<typename _Tp>
+ constexpr bool
+ operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ {
+ return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
+ && (!__lhs || *__lhs == *__rhs);
+ }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return !(__lhs == __rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ {
+ return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
+ }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs < __lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return !(__rhs < __lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return !(__lhs < __rhs); }
+
+ // [X.Y.9] Comparisons with nullopt.
+ template<typename _Tp>
+ constexpr bool
+ operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return !__lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return !__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return static_cast<bool>(__lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return static_cast<bool>(__rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
+ { return false; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return static_cast<bool>(__rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return static_cast<bool>(__lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
+ { return false; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return !__lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
+ { return true; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
+ { return true; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return !__rhs; }
+
+ // [X.Y.10] Comparisons with value type.
+ template<typename _Tp>
+ constexpr bool
+ operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return __lhs && *__lhs == __rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs && __lhs == *__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
+ { return !__lhs || *__lhs != __rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return !__rhs || __lhs != *__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return !__lhs || *__lhs < __rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs && __lhs < *__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return __lhs && __rhs < *__lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return !__rhs || *__rhs < __lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return !__lhs || !(__rhs < *__lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs && !(*__rhs < __lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return __lhs && !(*__lhs < __rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return !__rhs || !(__lhs < *__rhs); }
+
+ // [X.Y.11]
+ template<typename _Tp>
+ inline void
+ swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
+ noexcept(noexcept(__lhs.swap(__rhs)))
+ { __lhs.swap(__rhs); }
+
+ template<typename _Tp>
+ constexpr optional<typename decay<_Tp>::type>
+ make_optional(_Tp&& __t)
+ { return optional<typename decay<_Tp>::type> { std::forward<_Tp>(__t) }; }
+
+ // @} group optional
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
+ // [X.Y.12]
+ template<typename _Tp>
+ struct hash<experimental::optional<_Tp>>
+ {
+ using result_type = size_t;
+ using argument_type = experimental::optional<_Tp>;
+
+ size_t
+ operator()(const experimental::optional<_Tp>& __t) const
+ noexcept(noexcept(hash<_Tp> {}(*__t)))
+ {
+ // We pick an arbitrary hash for disengaged optionals which hopefully
+ // usual values of _Tp won't typically hash to.
+ constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
+ return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
+ }
+ };
+}
+
+#endif // C++14
+
+#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL