// -*- C++ -*- // Copyright (C) 2013-2018 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 // . /** @file include/optional * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_OPTIONAL #define _GLIBCXX_OPTIONAL 1 #pragma GCC system_header #if __cplusplus >= 201703L #include #include #include #include #include #include #include #include namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @addtogroup utilities * @{ */ #define __cpp_lib_optional 201603 template class optional; /// 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) { } }; /// Tag to disengage optional objects. inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; /** * @brief Exception class thrown when a disengaged optional object is * dereferenced. * @ingroup exceptions */ class bad_optional_access : public exception { public: bad_optional_access() { } virtual const char* what() const noexcept override { return "bad optional access"; } virtual ~bad_optional_access() noexcept = default; }; void __throw_bad_optional_access() __attribute__((__noreturn__)); // XXX Does not belong here. inline void __throw_bad_optional_access() { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); } // Payload for optionals with non-trivial destructor. template , bool /*_HasTrivialCopy */ = is_trivially_copy_assignable_v<_Tp> && is_trivially_copy_constructible_v<_Tp>, bool /*_HasTrivialMove */ = is_trivially_move_assignable_v<_Tp> && is_trivially_move_constructible_v<_Tp>> struct _Optional_payload { constexpr _Optional_payload() noexcept : _M_empty() { } template constexpr _Optional_payload(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } template constexpr _Optional_payload(std::initializer_list<_Up> __il, _Args&&... __args) : _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) { } constexpr _Optional_payload(bool __engaged, const _Optional_payload& __other) : _Optional_payload(__other) { } constexpr _Optional_payload(bool __engaged, _Optional_payload&& __other) : _Optional_payload(std::move(__other)) { } constexpr _Optional_payload(const _Optional_payload& __other) { if (__other._M_engaged) this->_M_construct(__other._M_payload); } constexpr _Optional_payload(_Optional_payload&& __other) { if (__other._M_engaged) this->_M_construct(std::move(__other._M_payload)); } constexpr _Optional_payload& operator=(const _Optional_payload& __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; } constexpr _Optional_payload& operator=(_Optional_payload&& __other) noexcept(__and_, 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; } using _Stored_type = remove_const_t<_Tp>; struct _Empty_byte { }; union { _Empty_byte _M_empty; _Stored_type _M_payload; }; bool _M_engaged = false; ~_Optional_payload() { if (_M_engaged) _M_payload.~_Stored_type(); } template void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) { ::new ((void *) std::__addressof(this->_M_payload)) _Stored_type(std::forward<_Args>(__args)...); this->_M_engaged = true; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return this->_M_payload; } constexpr const _Tp& _M_get() const noexcept { return this->_M_payload; } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { if (this->_M_engaged) { this->_M_engaged = false; this->_M_payload.~_Stored_type(); } } }; // Payload for potentially-constexpr optionals. template struct _Optional_payload<_Tp, true, true, true> { constexpr _Optional_payload() noexcept : _M_empty(), _M_engaged(false) { } template constexpr _Optional_payload(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } template constexpr _Optional_payload(std::initializer_list<_Up> __il, _Args&&... __args) : _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) { } constexpr _Optional_payload(bool __engaged, const _Optional_payload& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(__other._M_get()); } constexpr _Optional_payload(bool __engaged, _Optional_payload&& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(std::move(__other._M_get())); } using _Stored_type = remove_const_t<_Tp>; struct _Empty_byte { }; union { _Empty_byte _M_empty; _Stored_type _M_payload; }; bool _M_engaged; // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return this->_M_payload; } constexpr const _Tp& _M_get() const noexcept { return this->_M_payload; } }; // Payload for optionals with non-trivial copy assignment. template struct _Optional_payload<_Tp, true, false, true> { constexpr _Optional_payload() noexcept : _M_empty(), _M_engaged(false) { } template constexpr _Optional_payload(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } template constexpr _Optional_payload(std::initializer_list<_Up> __il, _Args&&... __args) : _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) { } constexpr _Optional_payload(bool __engaged, const _Optional_payload& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(__other._M_get()); } constexpr _Optional_payload(bool __engaged, _Optional_payload&& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(std::move(__other._M_get())); } _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; constexpr _Optional_payload& operator=(const _Optional_payload& __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_payload& operator=(_Optional_payload&& __other) = default; using _Stored_type = remove_const_t<_Tp>; struct _Empty_byte { }; union { _Empty_byte _M_empty; _Stored_type _M_payload; }; bool _M_engaged; template void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) { ::new ((void *) std::__addressof(this->_M_payload)) _Stored_type(std::forward<_Args>(__args)...); this->_M_engaged = true; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return this->_M_payload; } constexpr const _Tp& _M_get() const noexcept { return this->_M_payload; } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { if (this->_M_engaged) { this->_M_engaged = false; this->_M_payload.~_Stored_type(); } } }; // Payload for optionals with non-trivial move assignment. template struct _Optional_payload<_Tp, true, true, false> { constexpr _Optional_payload() noexcept : _M_empty(), _M_engaged(false) { } template constexpr _Optional_payload(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } template constexpr _Optional_payload(std::initializer_list<_Up> __il, _Args&&... __args) : _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) { } constexpr _Optional_payload(bool __engaged, const _Optional_payload& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(__other._M_get()); } constexpr _Optional_payload(bool __engaged, _Optional_payload&& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(std::move(__other._M_get())); } _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; _Optional_payload& operator=(const _Optional_payload& __other) = default; constexpr _Optional_payload& operator=(_Optional_payload&& __other) noexcept(__and_, 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; } using _Stored_type = remove_const_t<_Tp>; struct _Empty_byte { }; union { _Empty_byte _M_empty; _Stored_type _M_payload; }; bool _M_engaged; template void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) { ::new ((void *) std::__addressof(this->_M_payload)) _Stored_type(std::forward<_Args>(__args)...); this->_M_engaged = true; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return this->_M_payload; } constexpr const _Tp& _M_get() const noexcept { return this->_M_payload; } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { if (this->_M_engaged) { this->_M_engaged = false; this->_M_payload.~_Stored_type(); } } }; // Payload for optionals with non-trivial copy and move assignment. template struct _Optional_payload<_Tp, true, false, false> { constexpr _Optional_payload() noexcept : _M_empty(), _M_engaged(false) {} template constexpr _Optional_payload(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } template constexpr _Optional_payload(std::initializer_list<_Up> __il, _Args&&... __args) : _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) { } constexpr _Optional_payload(bool __engaged, const _Optional_payload& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(__other._M_get()); } constexpr _Optional_payload(bool __engaged, _Optional_payload&& __other) : _M_engaged(__engaged) { if (__engaged) _M_construct(std::move(__other._M_get())); } _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; constexpr _Optional_payload& operator=(const _Optional_payload& __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; } constexpr _Optional_payload& operator=(_Optional_payload&& __other) noexcept(__and_, 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; } using _Stored_type = remove_const_t<_Tp>; struct _Empty_byte { }; union { _Empty_byte _M_empty; _Stored_type _M_payload; }; bool _M_engaged; template void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) { ::new ((void *) std::__addressof(this->_M_payload)) _Stored_type(std::forward<_Args>(__args)...); this->_M_engaged = true; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return this->_M_payload; } constexpr const _Tp& _M_get() const noexcept { return this->_M_payload; } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { if (this->_M_engaged) { this->_M_engaged = false; this->_M_payload.~_Stored_type(); } } }; template class _Optional_base_impl { protected: using _Stored_type = remove_const_t<_Tp>; // The _M_construct operation has !_M_engaged as a precondition // while _M_destruct has _M_engaged as a precondition. template void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) { ::new (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload)) _Stored_type(std::forward<_Args>(__args)...); static_cast<_Dp*>(this)->_M_payload._M_engaged = true; } void _M_destruct() noexcept { static_cast<_Dp*>(this)->_M_payload._M_engaged = false; static_cast<_Dp*>(this)->_M_payload._M_payload.~_Stored_type(); } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { if (static_cast<_Dp*>(this)->_M_payload._M_engaged) static_cast<_Dp*>(this)->_M_destruct(); } }; /** * @brief Class template that takes care of copy/move constructors of optional * * Such a separate base class template is necessary in order to * conditionally make copy/move constructors trivial. * @see optional, _Enable_special_members */ template, bool = is_trivially_move_constructible_v<_Tp>> class _Optional_base // protected inheritance because optional needs to reach that base too : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> { friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; public: // Constructors for disengaged optionals. constexpr _Optional_base() = default; // Constructors for engaged optionals. template, bool> = false> constexpr explicit _Optional_base(in_place_t, _Args&&... __args) : _M_payload(in_place, std::forward<_Args>(__args)...) { } template&, _Args&&...>, bool> = false> constexpr explicit _Optional_base(in_place_t, initializer_list<_Up> __il, _Args&&... __args) : _M_payload(in_place, __il, std::forward<_Args>(__args)...) { } // Copy and move constructors. constexpr _Optional_base(const _Optional_base& __other) : _M_payload(__other._M_payload._M_engaged, __other._M_payload) { } constexpr _Optional_base(_Optional_base&& __other) noexcept(is_nothrow_move_constructible<_Tp>()) : _M_payload(__other._M_payload._M_engaged, std::move(__other._M_payload)) { } // Assignment operators. _Optional_base& operator=(const _Optional_base&) = default; _Optional_base& operator=(_Optional_base&&) = default; protected: constexpr bool _M_is_engaged() const noexcept { return this->_M_payload._M_engaged; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } constexpr const _Tp& _M_get() const noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } private: _Optional_payload<_Tp> _M_payload; }; template class _Optional_base<_Tp, false, true> : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> { friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; public: // Constructors for disengaged optionals. constexpr _Optional_base() = default; // Constructors for engaged optionals. template, bool> = false> constexpr explicit _Optional_base(in_place_t, _Args&&... __args) : _M_payload(in_place, std::forward<_Args>(__args)...) { } template&, _Args&&...>, bool> = false> constexpr explicit _Optional_base(in_place_t, initializer_list<_Up> __il, _Args&&... __args) : _M_payload(in_place, __il, std::forward<_Args>(__args)...) { } // Copy and move constructors. constexpr _Optional_base(const _Optional_base& __other) : _M_payload(__other._M_payload._M_engaged, __other._M_payload) { } constexpr _Optional_base(_Optional_base&& __other) = default; // Assignment operators. _Optional_base& operator=(const _Optional_base&) = default; _Optional_base& operator=(_Optional_base&&) = default; protected: constexpr bool _M_is_engaged() const noexcept { return this->_M_payload._M_engaged; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } constexpr const _Tp& _M_get() const noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } private: _Optional_payload<_Tp> _M_payload; }; template class _Optional_base<_Tp, true, false> : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> { friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; public: // Constructors for disengaged optionals. constexpr _Optional_base() = default; // Constructors for engaged optionals. template, bool> = false> constexpr explicit _Optional_base(in_place_t, _Args&&... __args) : _M_payload(in_place, std::forward<_Args>(__args)...) { } template&, _Args&&...>, bool> = false> constexpr explicit _Optional_base(in_place_t, initializer_list<_Up> __il, _Args&&... __args) : _M_payload(in_place, __il, std::forward<_Args>(__args)...) { } // Copy and move constructors. constexpr _Optional_base(const _Optional_base& __other) = default; constexpr _Optional_base(_Optional_base&& __other) noexcept(is_nothrow_move_constructible<_Tp>()) : _M_payload(__other._M_payload._M_engaged, std::move(__other._M_payload)) { } // Assignment operators. _Optional_base& operator=(const _Optional_base&) = default; _Optional_base& operator=(_Optional_base&&) = default; protected: constexpr bool _M_is_engaged() const noexcept { return this->_M_payload._M_engaged; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } constexpr const _Tp& _M_get() const noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } private: _Optional_payload<_Tp> _M_payload; }; template class _Optional_base<_Tp, true, true> : protected _Optional_base_impl<_Tp, _Optional_base<_Tp>> { friend class _Optional_base_impl<_Tp, _Optional_base<_Tp>>; public: // Constructors for disengaged optionals. constexpr _Optional_base() = default; // Constructors for engaged optionals. template, bool> = false> constexpr explicit _Optional_base(in_place_t, _Args&&... __args) : _M_payload(in_place, std::forward<_Args>(__args)...) { } template&, _Args&&...>, bool> = false> constexpr explicit _Optional_base(in_place_t, initializer_list<_Up> __il, _Args&&... __args) : _M_payload(in_place, __il, std::forward<_Args>(__args)...) { } // Copy and move constructors. constexpr _Optional_base(const _Optional_base& __other) = default; constexpr _Optional_base(_Optional_base&& __other) = default; // Assignment operators. _Optional_base& operator=(const _Optional_base&) = default; _Optional_base& operator=(_Optional_base&&) = default; protected: constexpr bool _M_is_engaged() const noexcept { return this->_M_payload._M_engaged; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } constexpr const _Tp& _M_get() const noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_payload._M_payload; } private: _Optional_payload<_Tp> _M_payload; }; template class optional; template using __converts_from_optional = __or_&>, is_constructible<_Tp, optional<_Up>&>, is_constructible<_Tp, const optional<_Up>&&>, is_constructible<_Tp, optional<_Up>&&>, is_convertible&, _Tp>, is_convertible&, _Tp>, is_convertible&&, _Tp>, is_convertible&&, _Tp>>; template using __assigns_from_optional = __or_&>, is_assignable<_Tp&, optional<_Up>&>, is_assignable<_Tp&, const optional<_Up>&&>, is_assignable<_Tp&, optional<_Up>&&>>; /** * @brief Class template for optional values. */ template class optional : private _Optional_base<_Tp>, private _Enable_copy_move< // Copy constructor. is_copy_constructible<_Tp>::value, // Copy assignment. __and_, is_copy_assignable<_Tp>>::value, // Move constructor. is_move_constructible<_Tp>::value, // Move assignment. __and_, is_move_assignable<_Tp>>::value, // Unique tag type. optional<_Tp>> { static_assert(!is_same_v, nullopt_t>); static_assert(!is_same_v, in_place_t>); static_assert(!is_reference_v<_Tp>); private: using _Base = _Optional_base<_Tp>; public: using value_type = _Tp; constexpr optional() = default; constexpr optional(nullopt_t) noexcept { } // Converting constructors for engaged optionals. template , decay_t<_Up>>>, __not_>>, is_constructible<_Tp, _Up&&>, is_convertible<_Up&&, _Tp> >::value, bool> = true> constexpr optional(_Up&& __t) : _Base(std::in_place, std::forward<_Up>(__t)) { } template , decay_t<_Up>>>, __not_>>, is_constructible<_Tp, _Up&&>, __not_> >::value, bool> = false> explicit constexpr optional(_Up&& __t) : _Base(std::in_place, std::forward<_Up>(__t)) { } template >, is_constructible<_Tp, const _Up&>, is_convertible, __not_<__converts_from_optional<_Tp, _Up>> >::value, bool> = true> constexpr optional(const optional<_Up>& __t) { if (__t) emplace(*__t); } template >, is_constructible<_Tp, const _Up&>, __not_>, __not_<__converts_from_optional<_Tp, _Up>> >::value, bool> = false> explicit constexpr optional(const optional<_Up>& __t) { if (__t) emplace(*__t); } template >, is_constructible<_Tp, _Up&&>, is_convertible<_Up&&, _Tp>, __not_<__converts_from_optional<_Tp, _Up>> >::value, bool> = true> constexpr optional(optional<_Up>&& __t) { if (__t) emplace(std::move(*__t)); } template >, is_constructible<_Tp, _Up&&>, __not_>, __not_<__converts_from_optional<_Tp, _Up>> >::value, bool> = false> explicit constexpr optional(optional<_Up>&& __t) { if (__t) emplace(std::move(*__t)); } template, bool> = false> explicit constexpr optional(in_place_t, _Args&&... __args) : _Base(std::in_place, std::forward<_Args>(__args)...) { } template&, _Args&&...>, bool> = false> explicit constexpr optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } // Assignment operators. optional& operator=(nullopt_t) noexcept { this->_M_reset(); return *this; } template enable_if_t<__and_< __not_, decay_t<_Up>>>, is_constructible<_Tp, _Up>, __not_<__and_, is_same<_Tp, decay_t<_Up>>>>, is_assignable<_Tp&, _Up>>::value, optional&> operator=(_Up&& __u) { if (this->_M_is_engaged()) this->_M_get() = std::forward<_Up>(__u); else this->_M_construct(std::forward<_Up>(__u)); return *this; } template enable_if_t<__and_< __not_>, is_constructible<_Tp, const _Up&>, is_assignable<_Tp&, _Up>, __not_<__converts_from_optional<_Tp, _Up>>, __not_<__assigns_from_optional<_Tp, _Up>> >::value, optional&> operator=(const optional<_Up>& __u) { if (__u) { if (this->_M_is_engaged()) this->_M_get() = *__u; else this->_M_construct(*__u); } else { this->_M_reset(); } return *this; } template enable_if_t<__and_< __not_>, is_constructible<_Tp, _Up>, is_assignable<_Tp&, _Up>, __not_<__converts_from_optional<_Tp, _Up>>, __not_<__assigns_from_optional<_Tp, _Up>> >::value, optional&> operator=(optional<_Up>&& __u) { if (__u) { if (this->_M_is_engaged()) this->_M_get() = std::move(*__u); else this->_M_construct(std::move(*__u)); } else { this->_M_reset(); } return *this; } template enable_if_t::value, _Tp&> emplace(_Args&&... __args) { this->_M_reset(); this->_M_construct(std::forward<_Args>(__args)...); return this->_M_get(); } template enable_if_t&, _Args&&...>::value, _Tp&> emplace(initializer_list<_Up> __il, _Args&&... __args) { this->_M_reset(); this->_M_construct(__il, std::forward<_Args>(__args)...); return this->_M_get(); } // Destructor is implicit, implemented in _Optional_base. // Swap. void swap(optional& __other) noexcept(is_nothrow_move_constructible<_Tp>() && is_nothrow_swappable_v<_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(); } } // Observers. constexpr const _Tp* operator->() const { return std::__addressof(this->_M_get()); } constexpr _Tp* operator->() { return std::__addressof(this->_M_get()); } constexpr const _Tp& operator*() const& { return this->_M_get(); } constexpr _Tp& operator*()& { return this->_M_get(); } constexpr _Tp&& operator*()&& { return std::move(this->_M_get()); } constexpr const _Tp&& operator*() const&& { return std::move(this->_M_get()); } constexpr explicit operator bool() const noexcept { return this->_M_is_engaged(); } constexpr bool has_value() const noexcept { return this->_M_is_engaged(); } constexpr const _Tp& value() const& { return this->_M_is_engaged() ? this->_M_get() : (__throw_bad_optional_access(), this->_M_get()); } constexpr _Tp& value()& { return this->_M_is_engaged() ? this->_M_get() : (__throw_bad_optional_access(), this->_M_get()); } constexpr _Tp&& value()&& { return this->_M_is_engaged() ? std::move(this->_M_get()) : (__throw_bad_optional_access(), std::move(this->_M_get())); } constexpr const _Tp&& value() const&& { return this->_M_is_engaged() ? std::move(this->_M_get()) : (__throw_bad_optional_access(), std::move(this->_M_get())); } template constexpr _Tp value_or(_Up&& __u) const& { static_assert(is_copy_constructible_v<_Tp>); static_assert(is_convertible_v<_Up&&, _Tp>); return this->_M_is_engaged() ? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u)); } template _Tp value_or(_Up&& __u) && { static_assert(is_move_constructible_v<_Tp>); static_assert(is_convertible_v<_Up&&, _Tp>); return this->_M_is_engaged() ? std::move(this->_M_get()) : static_cast<_Tp>(std::forward<_Up>(__u)); } void reset() noexcept { this->_M_reset(); } }; template using __optional_relop_t = enable_if_t::value, bool>; // Comparisons between optional values. template constexpr auto operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_relop_t() == declval<_Up>())> { return static_cast(__lhs) == static_cast(__rhs) && (!__lhs || *__lhs == *__rhs); } template constexpr auto operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_relop_t() != declval<_Up>())> { return static_cast(__lhs) != static_cast(__rhs) || (static_cast(__lhs) && *__lhs != *__rhs); } template constexpr auto operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_relop_t() < declval<_Up>())> { return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs); } template constexpr auto operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_relop_t() > declval<_Up>())> { return static_cast(__lhs) && (!__rhs || *__lhs > *__rhs); } template constexpr auto operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_relop_t() <= declval<_Up>())> { return !__lhs || (static_cast(__rhs) && *__lhs <= *__rhs); } template constexpr auto operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_relop_t() >= declval<_Up>())> { return !__rhs || (static_cast(__lhs) && *__lhs >= *__rhs); } // Comparisons with nullopt. template constexpr bool operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept { return !__lhs; } template constexpr bool operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept { return !__rhs; } template constexpr bool operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept { return static_cast(__lhs); } template constexpr bool operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept { return static_cast(__rhs); } template constexpr bool operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept { return false; } template constexpr bool operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept { return static_cast(__rhs); } template constexpr bool operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept { return static_cast(__lhs); } template constexpr bool operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept { return false; } template constexpr bool operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept { return !__lhs; } template constexpr bool operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept { return true; } template constexpr bool operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept { return true; } template constexpr bool operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept { return !__rhs; } // Comparisons with value type. template constexpr auto operator==(const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_relop_t() == declval<_Up>())> { return __lhs && *__lhs == __rhs; } template constexpr auto operator==(const _Up& __lhs, const optional<_Tp>& __rhs) -> __optional_relop_t() == declval<_Tp>())> { return __rhs && __lhs == *__rhs; } template constexpr auto operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_relop_t() != declval<_Up>())> { return !__lhs || *__lhs != __rhs; } template constexpr auto operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) -> __optional_relop_t() != declval<_Tp>())> { return !__rhs || __lhs != *__rhs; } template constexpr auto operator<(const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_relop_t() < declval<_Up>())> { return !__lhs || *__lhs < __rhs; } template constexpr auto operator<(const _Up& __lhs, const optional<_Tp>& __rhs) -> __optional_relop_t() < declval<_Tp>())> { return __rhs && __lhs < *__rhs; } template constexpr auto operator>(const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_relop_t() > declval<_Up>())> { return __lhs && *__lhs > __rhs; } template constexpr auto operator>(const _Up& __lhs, const optional<_Tp>& __rhs) -> __optional_relop_t() > declval<_Tp>())> { return !__rhs || __lhs > *__rhs; } template constexpr auto operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_relop_t() <= declval<_Up>())> { return !__lhs || *__lhs <= __rhs; } template constexpr auto operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) -> __optional_relop_t() <= declval<_Tp>())> { return __rhs && __lhs <= *__rhs; } template constexpr auto operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_relop_t() >= declval<_Up>())> { return __lhs && *__lhs >= __rhs; } template constexpr auto operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) -> __optional_relop_t() >= declval<_Tp>())> { return !__rhs || __lhs >= *__rhs; } // Swap and creation functions. // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2748. swappable traits for optionals template inline enable_if_t && is_swappable_v<_Tp>> swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) noexcept(noexcept(__lhs.swap(__rhs))) { __lhs.swap(__rhs); } template enable_if_t && is_swappable_v<_Tp>)> swap(optional<_Tp>&, optional<_Tp>&) = delete; template constexpr optional> make_optional(_Tp&& __t) { return optional> { std::forward<_Tp>(__t) }; } template constexpr optional<_Tp> make_optional(_Args&&... __args) { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; } template constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; } // Hash. template, bool = __poison_hash<_Up>::__enable_hash_call> struct __optional_hash_call_base { size_t operator()(const optional<_Tp>& __t) const noexcept(noexcept(hash<_Up>{}(*__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(-3333); return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; } }; template struct __optional_hash_call_base<_Tp, _Up, false> {}; template struct hash> : private __poison_hash>, public __optional_hash_call_base<_Tp> { using result_type [[__deprecated__]] = size_t; using argument_type [[__deprecated__]] = optional<_Tp>; }; template struct __is_fast_hash>> : __is_fast_hash> { }; /// @} #if __cpp_deduction_guides >= 201606 template optional(_Tp) -> optional<_Tp>; #endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // C++17 #endif // _GLIBCXX_OPTIONAL