// -*- C++ -*- // Copyright (C) 2013-2025 Free Software Foundation, Inc. // Copyright The GNU Toolchain Authors. // // 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 #ifdef _GLIBCXX_SYSHDR #pragma GCC system_header #endif #define __glibcxx_want_freestanding_optional #define __glibcxx_want_optional #define __glibcxx_want_optional_range_support #define __glibcxx_want_constrained_equality #include #ifdef __cpp_lib_optional // C++ >= 17 #include #include #include #include #include #include #include #include // _Construct #include // in_place_t #if __cplusplus > 201703L # include # include // std::__invoke #endif #if __cplusplus > 202002L # include #endif #ifdef __cpp_lib_optional_range_support // C++ >= 26 # include # include # include #endif namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @addtogroup utilities * @{ */ 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) noexcept { } }; /// Tag to disengage optional objects. inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; template struct _Optional_func { _Fn& _M_f; }; /** * @brief Exception class thrown when a disengaged optional object is * dereferenced. * @ingroup exceptions */ class bad_optional_access : public exception { public: bad_optional_access() = default; virtual ~bad_optional_access() = default; const char* what() const noexcept override { return "bad optional access"; } }; // XXX Does not belong here. [[__noreturn__]] inline void __throw_bad_optional_access() { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); } // This class template manages construction/destruction of // the contained value for a std::optional. template struct _Optional_payload_base { using _Stored_type = remove_const_t<_Tp>; _Optional_payload_base() = default; ~_Optional_payload_base() = default; template constexpr _Optional_payload_base(in_place_t __tag, _Args&&... __args) : _M_payload(__tag, std::forward<_Args>(__args)...), _M_engaged(true) { } template constexpr _Optional_payload_base(std::initializer_list<_Up> __il, _Args&&... __args) : _M_payload(__il, std::forward<_Args>(__args)...), _M_engaged(true) { } // Constructor used by _Optional_base copy constructor when the // contained value is not trivially copy constructible. constexpr _Optional_payload_base(bool /* __engaged */, const _Optional_payload_base& __other) { if (__other._M_engaged) this->_M_construct(__other._M_get()); } // Constructor used by _Optional_base move constructor when the // contained value is not trivially move constructible. constexpr _Optional_payload_base(bool /* __engaged */, _Optional_payload_base&& __other) { if (__other._M_engaged) this->_M_construct(std::move(__other._M_get())); } // Copy constructor is only used to when the contained value is // trivially copy constructible. _Optional_payload_base(const _Optional_payload_base&) = default; // Move constructor is only used to when the contained value is // trivially copy constructible. _Optional_payload_base(_Optional_payload_base&&) = default; _Optional_payload_base& operator=(const _Optional_payload_base&) = default; _Optional_payload_base& operator=(_Optional_payload_base&&) = default; // used to perform non-trivial copy assignment. constexpr void _M_copy_assign(const _Optional_payload_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(); } } // used to perform non-trivial move assignment. constexpr void _M_move_assign(_Optional_payload_base&& __other) noexcept(__and_v, 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(); } } struct _Empty_byte { }; template> union _Storage { constexpr _Storage() noexcept : _M_empty() { } template constexpr _Storage(in_place_t, _Args&&... __args) : _M_value(std::forward<_Args>(__args)...) { } template constexpr _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) : _M_value(__il, std::forward<_Args>(__args)...) { } #if __cplusplus >= 202002L template constexpr _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), std::forward<_Arg>(__arg))) { } #endif #if __cpp_concepts >= 202002L // Conditionally trivial special member functions ~_Storage() = default; // User-provided destructor is needed when _Up has non-trivial dtor. _GLIBCXX20_CONSTEXPR ~_Storage() requires (!is_trivially_destructible_v<_Up>) { } _Storage(const _Storage&) = default; _Storage(_Storage&&) = default; _Storage& operator=(const _Storage&) = default; _Storage& operator=(_Storage&&) = default; #endif _Empty_byte _M_empty; _Up _M_value; }; #if __cpp_concepts < 202002L template union _Storage<_Up, false> { constexpr _Storage() noexcept : _M_empty() { } template constexpr _Storage(in_place_t, _Args&&... __args) : _M_value(std::forward<_Args>(__args)...) { } template constexpr _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) : _M_value(__il, std::forward<_Args>(__args)...) { } #if __cplusplus >= 202002L template constexpr _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), std::forward<_Arg>(__arg))) { } #endif // User-provided destructor is needed when _Up has non-trivial dtor. _GLIBCXX20_CONSTEXPR ~_Storage() { } _Storage(const _Storage&) = default; _Storage(_Storage&&) = default; _Storage& operator=(const _Storage&) = default; _Storage& operator=(_Storage&&) = default; _Empty_byte _M_empty; _Up _M_value; }; #endif _Storage<_Stored_type> _M_payload; bool _M_engaged = false; template constexpr void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) { std::_Construct(std::__addressof(this->_M_payload._M_value), std::forward<_Args>(__args)...); this->_M_engaged = true; } constexpr void _M_destroy() noexcept { _M_engaged = false; _M_payload._M_value.~_Stored_type(); } #if __cplusplus >= 202002L template constexpr void _M_apply(_Optional_func<_Fn> __f, _Up&& __x) { std::construct_at(std::__addressof(this->_M_payload), __f, std::forward<_Up>(__x)); _M_engaged = true; } #endif // The _M_get() operations have _M_engaged as a precondition. // They exist to access the contained value with the appropriate // const-qualification, because _M_payload has had the const removed. constexpr _Tp& _M_get() noexcept { return this->_M_payload._M_value; } constexpr const _Tp& _M_get() const noexcept { return this->_M_payload._M_value; } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { if (this->_M_engaged) _M_destroy(); else // This seems redundant but improves codegen, see PR 112480. this->_M_engaged = false; } }; // Class template that manages the payload for optionals. 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; // Payload for potentially-constexpr optionals (trivial copy/move/destroy). template struct _Optional_payload<_Tp, true, true, true> : _Optional_payload_base<_Tp> { using _Optional_payload_base<_Tp>::_Optional_payload_base; _Optional_payload() = default; }; // Payload for optionals with non-trivial copy construction/assignment. template struct _Optional_payload<_Tp, true, false, true> : _Optional_payload_base<_Tp> { using _Optional_payload_base<_Tp>::_Optional_payload_base; _Optional_payload() = default; ~_Optional_payload() = default; _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; _Optional_payload& operator=(_Optional_payload&&) = default; // Non-trivial copy assignment. constexpr _Optional_payload& operator=(const _Optional_payload& __other) { this->_M_copy_assign(__other); return *this; } }; // Payload for optionals with non-trivial move construction/assignment. template struct _Optional_payload<_Tp, true, true, false> : _Optional_payload_base<_Tp> { using _Optional_payload_base<_Tp>::_Optional_payload_base; _Optional_payload() = default; ~_Optional_payload() = default; _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; _Optional_payload& operator=(const _Optional_payload&) = default; // Non-trivial move assignment. constexpr _Optional_payload& operator=(_Optional_payload&& __other) noexcept(__and_v, is_nothrow_move_assignable<_Tp>>) { this->_M_move_assign(std::move(__other)); return *this; } }; // Payload for optionals with non-trivial copy and move assignment. template struct _Optional_payload<_Tp, true, false, false> : _Optional_payload_base<_Tp> { using _Optional_payload_base<_Tp>::_Optional_payload_base; _Optional_payload() = default; ~_Optional_payload() = default; _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; // Non-trivial copy assignment. constexpr _Optional_payload& operator=(const _Optional_payload& __other) { this->_M_copy_assign(__other); return *this; } // Non-trivial move assignment. constexpr _Optional_payload& operator=(_Optional_payload&& __other) noexcept(__and_v, is_nothrow_move_assignable<_Tp>>) { this->_M_move_assign(std::move(__other)); return *this; } }; // Payload for optionals with non-trivial destructors. template struct _Optional_payload<_Tp, false, _Copy, _Move> : _Optional_payload<_Tp, true, false, false> { // Base class implements all the constructors and assignment operators: using _Optional_payload<_Tp, true, false, false>::_Optional_payload; _Optional_payload() = default; _Optional_payload(const _Optional_payload&) = default; _Optional_payload(_Optional_payload&&) = default; _Optional_payload& operator=(const _Optional_payload&) = default; _Optional_payload& operator=(_Optional_payload&&) = default; // Destructor needs to destroy the contained value: _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); } }; /** * @brief Class template that provides copy/move constructors of optional. * * Such a separate base class template is necessary in order to * conditionally make copy/move constructors trivial. * * When the contained value is trivially copy/move constructible, * the copy/move constructors of _Optional_base will invoke the * trivial copy/move constructor of _Optional_payload. Otherwise, * they will invoke _Optional_payload(bool, const _Optional_payload&) * or _Optional_payload(bool, _Optional_payload&&) to initialize * the contained value, if copying/moving an engaged optional. * * Whether the other special members are trivial is determined by the * _Optional_payload<_Tp> specialization used for the _M_payload member. * * @see optional, _Enable_special_members */ template, bool = is_trivially_move_constructible_v<_Tp>> struct _Optional_base { // 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) noexcept(is_nothrow_copy_constructible_v<_Tp>) : _M_payload(__other._M_payload._M_engaged, __other._M_payload) { } constexpr _Optional_base(_Optional_base&& __other) noexcept(is_nothrow_move_constructible_v<_Tp>) : _M_payload(__other._M_payload._M_engaged, std::move(__other._M_payload)) { } #if __cpp_concepts >= 202002L // Conditionally trivial special member functions // Define these in the primary template if possible, so that we don't // need to use partial specializations of this class template. constexpr _Optional_base(const _Optional_base&) requires is_trivially_copy_constructible_v<_Tp> = default; constexpr _Optional_base(_Optional_base&&) requires is_trivially_move_constructible_v<_Tp> = default; #endif // Assignment operators. _Optional_base& operator=(const _Optional_base&) = default; _Optional_base& operator=(_Optional_base&&) = default; _Optional_payload<_Tp> _M_payload; protected: // For the primary template, we define these functions here. 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 constexpr void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) { _M_payload._M_construct(std::forward<_Args>(__args)...); } constexpr void _M_destruct() noexcept { _M_payload._M_destroy(); } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { _M_payload._M_reset(); } constexpr bool _M_is_engaged() const noexcept { return _M_payload._M_engaged; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return _M_payload._M_get(); } constexpr const _Tp& _M_get() const noexcept { return _M_payload._M_get(); } }; #if __cpp_concepts < 202002L // If P0848R3 "Conditionally Trivial Special Member Functions" is not // supported (as determined from the __cpp_concepts macro value), the // _Optional_base primary template only has non-trivial copy and move // constructors. Use partial specializations of _Optional_base // that have a trivial copy and/or move constructor. // Common base class for _Optional_base to avoid repeating these // member functions in each partial specialization. // Only used if P0848R3 "Conditionally Trivial Special Member Functions" // is not supported, as indicated by the __cpp_concepts value. 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 constexpr void _M_construct(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) { static_cast<_Dp*>(this)->_M_payload._M_construct( std::forward<_Args>(__args)...); } constexpr void _M_destruct() noexcept { static_cast<_Dp*>(this)->_M_payload._M_destroy(); } // _M_reset is a 'safe' operation with no precondition. constexpr void _M_reset() noexcept { static_cast<_Dp*>(this)->_M_payload._M_reset(); } constexpr bool _M_is_engaged() const noexcept { return static_cast(this)->_M_payload._M_engaged; } // The _M_get operations have _M_engaged as a precondition. constexpr _Tp& _M_get() noexcept { return static_cast<_Dp*>(this)->_M_payload._M_get(); } constexpr const _Tp& _M_get() const noexcept { return static_cast(this)->_M_payload._M_get(); } }; template struct _Optional_base<_Tp, false, true> // trivial move ctor : _Optional_base_impl<_Tp, _Optional_base<_Tp>> { // 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; _Optional_payload<_Tp> _M_payload; }; template struct _Optional_base<_Tp, true, false> // trivial copy ctor : _Optional_base_impl<_Tp, _Optional_base<_Tp>> { // 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_v<_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; _Optional_payload<_Tp> _M_payload; }; template struct _Optional_base<_Tp, true, true> // trivial copy and move ctors : _Optional_base_impl<_Tp, _Optional_base<_Tp>> { // 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; _Optional_payload<_Tp> _M_payload; }; #endif // __cpp_concepts template inline constexpr bool __is_optional_v = false; template inline constexpr bool __is_optional_v> = true; template using __converts_from_any_cvref = __or_< is_constructible<_Tp, _Wp&>, is_convertible<_Wp&, _Tp>, is_constructible<_Tp, _Wp>, is_convertible<_Wp, _Tp>, is_constructible<_Tp, const _Wp&>, is_convertible, is_constructible<_Tp, const _Wp>, is_convertible >; template using __converts_from_optional = __converts_from_any_cvref<_Tp, optional<_Up>>; template using __assigns_from_optional = __or_&>, is_assignable<_Tp&, optional<_Up>&>, is_assignable<_Tp&, const optional<_Up>&&>, is_assignable<_Tp&, optional<_Up>&&>>; #if __cpp_concepts && __cpp_conditional_explicit && __glibcxx_remove_cvref # define _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL 1 #endif template inline constexpr bool __is_valid_contained_type_for_optional = ( #if __cpp_lib_optional >= 202506L is_lvalue_reference_v<_Tp> || #endif (is_object_v<_Tp> && is_destructible_v<_Tp> && !is_array_v<_Tp>) ) && !is_same_v>, nullopt_t> && !is_same_v>, in_place_t>; /** * @brief Class template for optional values. */ template class optional : private _Optional_base<_Tp>, private _Enable_copy_move< // Copy constructor. is_copy_constructible_v<_Tp>, // Copy assignment. __and_v, is_copy_assignable<_Tp>>, // Move constructor. is_move_constructible_v<_Tp>, // Move assignment. __and_v, is_move_assignable<_Tp>>, // Unique tag type. optional<_Tp>> { static_assert(__is_valid_contained_type_for_optional<_Tp>); private: using _Base = _Optional_base<_Tp>; // SFINAE helpers // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3836. std::expected conversion constructor // expected(const expected&) should take precedence over // expected(U&&) with operator bool #ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL template> static constexpr bool __not_constructing_bool_from_optional = true; // If T is cv bool, remove_cvref_t is not a specialization of optional // i.e. do not initialize a bool from optional::operator bool(). template static constexpr bool __not_constructing_bool_from_optional<_From, bool> = !__is_optional_v>; // If T is not cv bool, converts-from-any-cvref> is false. // The constructor that converts from optional is disabled if the // contained value can be initialized from optional, so that the // optional(U&&) constructor can be used instead. template> static constexpr bool __construct_from_contained_value = !__converts_from_optional<_Tp, _From>::value; // However, optional can always be converted to bool, so don't apply // this constraint when T is cv bool. template static constexpr bool __construct_from_contained_value<_From, bool> = true; #else template> struct __not_constructing_bool_from_optional : true_type { }; template struct __not_constructing_bool_from_optional<_From, bool> : bool_constant>> { }; template> struct __construct_from_contained_value : __not_<__converts_from_optional<_Tp, _From>> { }; template struct __construct_from_contained_value<_From, bool> : true_type { }; template using __not_self = __not_>>; template using __not_tag = __not_>>; template using _Requires = enable_if_t<__and_v<_Cond...>, bool>; #endif public: using value_type = _Tp; #ifdef __cpp_lib_optional_range_support // >= C++26 using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>; using const_iterator = __gnu_cxx::__normal_iterator; #endif constexpr optional() noexcept { } constexpr optional(nullopt_t) noexcept { } // Converting constructors for engaged optionals. #ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL template> requires (!is_same_v>) && (!is_same_v>) && is_constructible_v<_Tp, _Up> && __not_constructing_bool_from_optional<_Up> constexpr explicit(!is_convertible_v<_Up, _Tp>) optional(_Up&& __t) noexcept(is_nothrow_constructible_v<_Tp, _Up>) : _Base(std::in_place, std::forward<_Up>(__t)) { } template requires (!is_same_v<_Tp, _Up>) && is_constructible_v<_Tp, const _Up&> && __construct_from_contained_value<_Up> constexpr explicit(!is_convertible_v) optional(const optional<_Up>& __t) noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) { if (__t) emplace(__t._M_fwd()); } template requires (!is_same_v<_Tp, _Up>) && is_constructible_v<_Tp, _Up> && __construct_from_contained_value<_Up> constexpr explicit(!is_convertible_v<_Up, _Tp>) optional(optional<_Up>&& __t) noexcept(is_nothrow_constructible_v<_Tp, _Up>) { if (__t) emplace(std::move(__t)._M_fwd()); } template requires is_constructible_v<_Tp, _Args...> explicit constexpr optional(in_place_t, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>) : _Base(std::in_place, std::forward<_Args>(__args)...) { } template requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> explicit constexpr optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } #else template, _Requires<__not_self<_Up>, __not_tag<_Up>, is_constructible<_Tp, _Up>, is_convertible<_Up, _Tp>, __not_constructing_bool_from_optional<_Up>> = true> constexpr optional(_Up&& __t) noexcept(is_nothrow_constructible_v<_Tp, _Up>) : _Base(std::in_place, std::forward<_Up>(__t)) { } template, _Requires<__not_self<_Up>, __not_tag<_Up>, is_constructible<_Tp, _Up>, __not_>, __not_constructing_bool_from_optional<_Up>> = false> explicit constexpr optional(_Up&& __t) noexcept(is_nothrow_constructible_v<_Tp, _Up>) : _Base(std::in_place, std::forward<_Up>(__t)) { } template>, is_constructible<_Tp, const _Up&>, is_convertible, __construct_from_contained_value<_Up>> = true> constexpr optional(const optional<_Up>& __t) noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) { if (__t) emplace(__t._M_fwd()); } template>, is_constructible<_Tp, const _Up&>, __not_>, __construct_from_contained_value<_Up>> = false> explicit constexpr optional(const optional<_Up>& __t) noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) { if (__t) emplace(__t._M_fwd()); } template>, is_constructible<_Tp, _Up>, is_convertible<_Up, _Tp>, __construct_from_contained_value<_Up>> = true> constexpr optional(optional<_Up>&& __t) noexcept(is_nothrow_constructible_v<_Tp, _Up>) { if (__t) emplace(std::move(__t)._M_fwd()); } template>, is_constructible<_Tp, _Up>, __not_>, __construct_from_contained_value<_Up>> = false> explicit constexpr optional(optional<_Up>&& __t) noexcept(is_nothrow_constructible_v<_Tp, _Up>) { if (__t) emplace(std::move(__t)._M_fwd()); } template> = false> explicit constexpr optional(in_place_t, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>) : _Base(std::in_place, std::forward<_Args>(__args)...) { } template&, _Args...>> = false> explicit constexpr optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } #endif // Assignment operators. _GLIBCXX20_CONSTEXPR optional& operator=(nullopt_t) noexcept { this->_M_reset(); return *this; } template> #ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL requires (!is_same_v>) && (!(is_scalar_v<_Tp> && is_same_v<_Tp, decay_t<_Up>>)) && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> constexpr optional& #else enable_if_t<__and_v<__not_self<_Up>, __not_<__and_, is_same<_Tp, decay_t<_Up>>>>, is_constructible<_Tp, _Up>, is_assignable<_Tp&, _Up>>, optional&> #endif operator=(_Up&& __u) noexcept(__and_v, is_nothrow_assignable<_Tp&, _Up>>) { if (this->_M_is_engaged()) this->_M_get() = std::forward<_Up>(__u); else this->_M_construct(std::forward<_Up>(__u)); return *this; } template #ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL requires (!is_same_v<_Tp, _Up>) && is_constructible_v<_Tp, const _Up&> && is_assignable_v<_Tp&, const _Up&> && (!__converts_from_optional<_Tp, _Up>::value) && (!__assigns_from_optional<_Tp, _Up>::value) constexpr optional& #else enable_if_t<__and_v<__not_>, is_constructible<_Tp, const _Up&>, is_assignable<_Tp&, const _Up&>, __not_<__converts_from_optional<_Tp, _Up>>, __not_<__assigns_from_optional<_Tp, _Up>>>, optional&> #endif operator=(const optional<_Up>& __u) noexcept(__and_v, is_nothrow_assignable<_Tp&, const _Up&>>) { if (__u) { if (this->_M_is_engaged()) this->_M_get() = __u._M_fwd(); else this->_M_construct(__u._M_fwd()); } else { this->_M_reset(); } return *this; } template #ifdef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL requires (!is_same_v<_Tp, _Up>) && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> && (!__converts_from_optional<_Tp, _Up>::value) && (!__assigns_from_optional<_Tp, _Up>::value) constexpr optional& #else enable_if_t<__and_v<__not_>, is_constructible<_Tp, _Up>, is_assignable<_Tp&, _Up>, __not_<__converts_from_optional<_Tp, _Up>>, __not_<__assigns_from_optional<_Tp, _Up>>>, optional&> #endif operator=(optional<_Up>&& __u) noexcept(__and_v, is_nothrow_assignable<_Tp&, _Up>>) { if (__u) { if (this->_M_is_engaged()) this->_M_get() = std::move(__u)._M_fwd(); else this->_M_construct(std::move(__u)._M_fwd()); } else { this->_M_reset(); } return *this; } template _GLIBCXX20_CONSTEXPR enable_if_t, _Tp&> emplace(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>) { this->_M_reset(); this->_M_construct(std::forward<_Args>(__args)...); return this->_M_get(); } template _GLIBCXX20_CONSTEXPR enable_if_t&, _Args...>, _Tp&> emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) { this->_M_reset(); this->_M_construct(__il, std::forward<_Args>(__args)...); return this->_M_get(); } // Destructor is implicit, implemented in _Optional_base. // Swap. _GLIBCXX20_CONSTEXPR void swap(optional& __other) noexcept(is_nothrow_move_constructible_v<_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(); } } #ifdef __cpp_lib_optional_range_support // >= C++26 // Iterator support. constexpr iterator begin() noexcept { return iterator( this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr ); } constexpr const_iterator begin() const noexcept { return const_iterator( this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr ); } constexpr iterator end() noexcept { return begin() + has_value(); } constexpr const_iterator end() const noexcept { return begin() + has_value(); } #endif // __cpp_lib_optional_range_support // Observers. constexpr const _Tp* operator->() const noexcept { __glibcxx_assert(this->_M_is_engaged()); return std::__addressof(this->_M_get()); } constexpr _Tp* operator->() noexcept { __glibcxx_assert(this->_M_is_engaged()); return std::__addressof(this->_M_get()); } constexpr const _Tp& operator*() const& noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_get(); } constexpr _Tp& operator*()& noexcept { __glibcxx_assert(this->_M_is_engaged()); return this->_M_get(); } constexpr _Tp&& operator*()&& noexcept { __glibcxx_assert(this->_M_is_engaged()); return std::move(this->_M_get()); } constexpr const _Tp&& operator*() const&& noexcept { __glibcxx_assert(this->_M_is_engaged()); 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& { if (this->_M_is_engaged()) return this->_M_get(); __throw_bad_optional_access(); } constexpr _Tp& value()& { if (this->_M_is_engaged()) return this->_M_get(); __throw_bad_optional_access(); } constexpr _Tp&& value()&& { if (this->_M_is_engaged()) return std::move(this->_M_get()); __throw_bad_optional_access(); } constexpr const _Tp&& value() const&& { if (this->_M_is_engaged()) return std::move(this->_M_get()); __throw_bad_optional_access(); } // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4406. value_or return statement is inconsistent with Mandates template> constexpr remove_cv_t<_Tp> value_or(_Up&& __u) const& { using _Xp = remove_cv_t<_Tp>; static_assert(is_convertible_v); static_assert(is_convertible_v<_Up, _Xp>); if (this->_M_is_engaged()) return this->_M_get(); return std::forward<_Up>(__u); } template> constexpr remove_cv_t<_Tp> value_or(_Up&& __u) && { using _Xp = remove_cv_t<_Tp>; static_assert(is_convertible_v<_Tp, _Xp>); static_assert(is_convertible_v<_Up, _Xp>); if (this->_M_is_engaged()) return std::move(this->_M_get()); return std::forward<_Up>(__u); } #if __cpp_lib_optional >= 202110L // C++23 // [optional.monadic] template constexpr auto and_then(_Fn&& __f) & { using _Up = remove_cvref_t>; static_assert(__is_optional_v<_Up>, "the function passed to std::optional::and_then " "must return a std::optional"); if (has_value()) return std::__invoke(std::forward<_Fn>(__f), _M_get()); else return _Up(); } template constexpr auto and_then(_Fn&& __f) const & { using _Up = remove_cvref_t>; static_assert(__is_optional_v<_Up>, "the function passed to std::optional::and_then " "must return a std::optional"); if (has_value()) return std::__invoke(std::forward<_Fn>(__f), _M_get()); else return _Up(); } template constexpr auto and_then(_Fn&& __f) && { using _Up = remove_cvref_t>; static_assert(__is_optional_v<_Up>, "the function passed to std::optional::and_then " "must return a std::optional"); if (has_value()) return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get())); else return _Up(); } template constexpr auto and_then(_Fn&& __f) const && { using _Up = remove_cvref_t>; static_assert(__is_optional_v<_Up>, "the function passed to std::optional::and_then " "must return a std::optional"); if (has_value()) return std::__invoke(std::forward<_Fn>(__f), std::move(_M_get())); else return _Up(); } template constexpr auto transform(_Fn&& __f) & { using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get()); else return optional<_Up>(); } template constexpr auto transform(_Fn&& __f) const & { using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, _M_get()); else return optional<_Up>(); } template constexpr auto transform(_Fn&& __f) && { using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get())); else return optional<_Up>(); } template constexpr auto transform(_Fn&& __f) const && { using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(_M_get())); else return optional<_Up>(); } template requires invocable<_Fn> && copy_constructible<_Tp> constexpr optional or_else(_Fn&& __f) const& { using _Up = invoke_result_t<_Fn>; static_assert(is_same_v, optional>, "the function passed to std::optional::or_else " "must return a std::optional"); if (has_value()) return *this; else return std::forward<_Fn>(__f)(); } template requires invocable<_Fn> && move_constructible<_Tp> constexpr optional or_else(_Fn&& __f) && { using _Up = invoke_result_t<_Fn>; static_assert(is_same_v, optional>, "the function passed to std::optional::or_else " "must return a std::optional"); if (has_value()) return std::move(*this); else return std::forward<_Fn>(__f)(); } #endif _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); } private: using _Base::_M_get; [[__gnu__::__always_inline__]] constexpr _Tp& _M_fwd() & noexcept { return _M_get(); } [[__gnu__::__always_inline__]] constexpr _Tp&& _M_fwd() && noexcept { return std::move(_M_get()); } [[__gnu__::__always_inline__]] constexpr const _Tp& _M_fwd() const& noexcept { return _M_get(); } [[__gnu__::__always_inline__]] constexpr const _Tp&& _M_fwd() const&& noexcept { return std::move(_M_get()); } template friend class optional; #if __cpp_lib_optional >= 202110L // C++23 template explicit constexpr optional(_Optional_func<_Fn> __f, _Value&& __v) { this->_M_payload._M_apply(__f, std::forward<_Value>(__v)); } #endif }; #if __cpp_lib_optional >= 202506L // C++26 template class optional<_Tp&>; template constexpr bool __is_optional_ref_v = false; template constexpr bool __is_optional_ref_v> = true; template struct __optional_ref_base {}; #ifdef __cpp_lib_optional_range_support // >= C++26 template struct __optional_ref_base<_Tp[]> {}; template requires is_object_v<_Tp> struct __optional_ref_base<_Tp> { using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional<_Tp&>>; }; #endif // __cpp_lib_optional_range_support template class optional<_Tp&> : public __optional_ref_base<_Tp> { static_assert(__is_valid_contained_type_for_optional<_Tp&>); public: using value_type = _Tp; // Constructors. constexpr optional() noexcept = default; constexpr optional(nullopt_t) noexcept : optional() {} constexpr optional(const optional&) noexcept = default; template requires is_constructible_v<_Tp&, _Arg> && (!reference_constructs_from_temporary_v<_Tp&, _Arg>) explicit constexpr optional(in_place_t, _Arg&& __arg) { __convert_ref_init_val(std::forward<_Arg>(__arg)); } template requires (!is_same_v, optional>) && (!is_same_v, in_place_t>) && is_constructible_v<_Tp&, _Up> && (!reference_constructs_from_temporary_v<_Tp&, _Up>) explicit(!is_convertible_v<_Up, _Tp&>) constexpr optional(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) { __convert_ref_init_val(std::forward<_Up>(__u)); } template requires (!is_same_v, optional>) && (!is_same_v, in_place_t>) && is_constructible_v<_Tp&, _Up> && reference_constructs_from_temporary_v<_Tp&, _Up> explicit(!is_convertible_v<_Up, _Tp&>) constexpr optional(_Up&& __u) = delete; // optional & template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&> && (!reference_constructs_from_temporary_v<_Tp&, _Up&>) explicit(!is_convertible_v<_Up&, _Tp&>) constexpr optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) { if (__rhs) __convert_ref_init_val(__rhs._M_fwd()); } template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&> && reference_constructs_from_temporary_v<_Tp&, _Up&> explicit(!is_convertible_v<_Up&, _Tp&>) constexpr optional(optional<_Up>& __rhs) = delete; // const optional& template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up&> && (!reference_constructs_from_temporary_v<_Tp&, const _Up&>) explicit(!is_convertible_v) constexpr optional(const optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) { if (__rhs) __convert_ref_init_val(__rhs._M_fwd()); } template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up&> && reference_constructs_from_temporary_v<_Tp&, const _Up&> explicit(!is_convertible_v) constexpr optional(const optional<_Up>& __rhs) = delete; // optional&& template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up> && (!reference_constructs_from_temporary_v<_Tp&, _Up>) explicit(!is_convertible_v<_Up, _Tp&>) constexpr optional(optional<_Up>&& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) { if (__rhs) __convert_ref_init_val(std::move(__rhs)._M_fwd()); } template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up> && reference_constructs_from_temporary_v<_Tp&, _Up> explicit(!is_convertible_v<_Up, _Tp&>) constexpr optional(optional<_Up>&& __rhs) = delete; // const optional&& template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up> && (!reference_constructs_from_temporary_v<_Tp&, _Up>) explicit(!is_convertible_v) constexpr optional(const optional<_Up>&& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) { if (__rhs) __convert_ref_init_val(std::move(__rhs)._M_fwd()); } template requires (!is_same_v, optional<_Up>>) && (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, const _Up> && reference_constructs_from_temporary_v<_Tp&, const _Up> explicit(!is_convertible_v) constexpr optional(const optional<_Up>&& __rhs) = delete; constexpr ~optional() = default; // Assignment. constexpr optional& operator=(nullopt_t) noexcept { _M_val = nullptr; return *this; } constexpr optional& operator=(const optional&) noexcept = default; template requires is_constructible_v<_Tp&, _Up> && (!reference_constructs_from_temporary_v<_Tp&, _Up>) constexpr _Tp& emplace(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp&, _Up>) { __convert_ref_init_val(std::forward<_Up>(__u)); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4300. Missing Returns: element in optional::emplace return *_M_val; } // Swap. constexpr void swap(optional& __rhs) noexcept { std::swap(_M_val, __rhs._M_val); } #ifdef __cpp_lib_optional_range_support // >= C++26 // Iterator support. constexpr auto begin() const noexcept requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>) { return __gnu_cxx::__normal_iterator<_Tp*, optional>(_M_val); } constexpr auto end() const noexcept requires is_object_v<_Tp> && (!is_unbounded_array_v<_Tp>) { return begin() + has_value(); } #endif // __cpp_lib_optional_range_support // Observers. constexpr _Tp* operator->() const noexcept { __glibcxx_assert(_M_val); // hardened precondition return _M_val; } constexpr _Tp& operator*() const noexcept { __glibcxx_assert(_M_val); // hardened precondition return *_M_val; } constexpr explicit operator bool() const noexcept { return _M_val; } constexpr bool has_value() const noexcept { return _M_val; } constexpr _Tp& value() const { if (_M_val) return *_M_val; __throw_bad_optional_access(); } // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4304. std::optional is ill-formed due to value_or template> requires is_object_v<_Tp> && (!is_array_v<_Tp>) constexpr decay_t<_Tp> value_or(_Up&& __u) const { using _Xp = remove_cv_t<_Tp>; static_assert(is_convertible_v<_Tp&, _Xp>); static_assert(is_convertible_v<_Up, _Xp>); if (_M_val) return *_M_val; return std::forward<_Up>(__u); } // Monadic operations. template constexpr auto and_then(_Fn&& __f) const { using _Up = remove_cvref_t>; static_assert(__is_optional_v<_Up>, "the function passed to std::optional::and_then " "must return a std::optional"); if (has_value()) return std::__invoke(std::forward<_Fn>(__f), *_M_val); else return _Up(); } template constexpr optional>> transform(_Fn&& __f) const { using _Up = remove_cv_t>; if (has_value()) return optional<_Up>(_Optional_func<_Fn>{__f}, *_M_val); else return optional<_Up>(); } template requires invocable<_Fn> constexpr optional or_else(_Fn&& __f) const { static_assert(is_same_v>, optional>, "the function passed to std::optional::or_else " "must return a std::optional"); // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4367. Improve optional::or_else if (has_value()) return *this; else return std::forward<_Fn>(__f)(); } // Modifiers. constexpr void reset() noexcept { _M_val = nullptr; } private: _Tp *_M_val = nullptr; [[__gnu__::__always_inline__]] constexpr _Tp& _M_fwd() const noexcept { return *_M_val; } template friend class optional; template constexpr void __convert_ref_init_val(_Up&& __u) noexcept { _Tp& __r(std::forward<_Up>(__u)); _M_val = std::addressof(__r); } template explicit constexpr optional(_Optional_func<_Fn> __f, _Value&& __v) { _Tp& __r = std::__invoke(std::forward<_Fn>(__f._M_f), std::forward<_Value>(__v)); _M_val = std::addressof(__r); } }; #endif // __cpp_lib_optional >= 202506L template using __optional_relop_t = enable_if_t, bool>; template using __optional_eq_t = __optional_relop_t< decltype(std::declval() == std::declval()) >; template using __optional_ne_t = __optional_relop_t< decltype(std::declval() != std::declval()) >; template using __optional_lt_t = __optional_relop_t< decltype(std::declval() < std::declval()) >; template using __optional_gt_t = __optional_relop_t< decltype(std::declval() > std::declval()) >; template using __optional_le_t = __optional_relop_t< decltype(std::declval() <= std::declval()) >; template using __optional_ge_t = __optional_relop_t< decltype(std::declval() >= std::declval()) >; // Comparisons between optional values. template constexpr auto operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_eq_t<_Tp, _Up> { if (__lhs.has_value() != __rhs.has_value()) return false; if (!__lhs.has_value()) return true; return *__lhs == *__rhs; } template constexpr auto operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_ne_t<_Tp, _Up> { if (__lhs.has_value() != __rhs.has_value()) return true; if (!__lhs.has_value()) return false; return *__lhs != *__rhs; } template constexpr auto operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_lt_t<_Tp, _Up> { if (!__rhs.has_value()) return false; if (!__lhs.has_value()) return true; return *__lhs < *__rhs; } template constexpr auto operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_gt_t<_Tp, _Up> { if (!__lhs.has_value()) return false; if (!__rhs.has_value()) return true; return *__lhs > *__rhs; } template constexpr auto operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_le_t<_Tp, _Up> { if (!__lhs.has_value()) return true; if (!__rhs.has_value()) return false; return *__lhs <= *__rhs; } template constexpr auto operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) -> __optional_ge_t<_Tp, _Up> { if (!__rhs.has_value()) return true; if (!__lhs.has_value()) return false; return *__lhs >= *__rhs; } #ifdef __cpp_lib_three_way_comparison template _Up> [[nodiscard]] constexpr compare_three_way_result_t<_Tp, _Up> operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) { return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); } #endif // Comparisons with nullopt. template [[nodiscard]] constexpr bool operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept { return !__lhs; } #ifdef __cpp_lib_three_way_comparison template [[nodiscard]] constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept { return bool(__x) <=> false; } #else 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; } #endif // three-way-comparison #if __cpp_lib_concepts // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4072. std::optional comparisons: constrain harder # define _REQUIRES_NOT_OPTIONAL(T) requires (!__is_optional_v) #else # define _REQUIRES_NOT_OPTIONAL(T) #endif // Comparisons with value type. template _REQUIRES_NOT_OPTIONAL(_Up) constexpr auto operator== [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_eq_t<_Tp, _Up> { if (__lhs.has_value()) return *__lhs == __rhs; return false; } template _REQUIRES_NOT_OPTIONAL(_Tp) constexpr auto operator== [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs) -> __optional_eq_t<_Tp, _Up> { if (__rhs.has_value()) return __lhs == *__rhs; return false; } template _REQUIRES_NOT_OPTIONAL(_Up) constexpr auto operator!= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_ne_t<_Tp, _Up> { if (__lhs.has_value()) return *__lhs != __rhs; return true; } template _REQUIRES_NOT_OPTIONAL(_Tp) constexpr auto operator!= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs) -> __optional_ne_t<_Tp, _Up> { if (__rhs.has_value()) return __lhs != *__rhs; return true; } template _REQUIRES_NOT_OPTIONAL(_Up) constexpr auto operator< [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_lt_t<_Tp, _Up> { if (__lhs.has_value()) return *__lhs < __rhs; return true; } template _REQUIRES_NOT_OPTIONAL(_Tp) constexpr auto operator< [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs) -> __optional_lt_t<_Tp, _Up> { if (__rhs.has_value()) return __lhs < *__rhs; return false; } template _REQUIRES_NOT_OPTIONAL(_Up) constexpr auto operator> [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_gt_t<_Tp, _Up> { if (__lhs.has_value()) return *__lhs > __rhs; return false; } template _REQUIRES_NOT_OPTIONAL(_Tp) constexpr auto operator> [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs) -> __optional_gt_t<_Tp, _Up> { if (__rhs.has_value()) return __lhs > *__rhs; return true; } template _REQUIRES_NOT_OPTIONAL(_Up) constexpr auto operator<= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_le_t<_Tp, _Up> { if (__lhs.has_value()) return *__lhs <= __rhs; return true; } template _REQUIRES_NOT_OPTIONAL(_Tp) constexpr auto operator<= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs) -> __optional_le_t<_Tp, _Up> { if (__rhs.has_value()) return __lhs <= *__rhs; return false; } template _REQUIRES_NOT_OPTIONAL(_Up) constexpr auto operator>= [[nodiscard]] (const optional<_Tp>& __lhs, const _Up& __rhs) -> __optional_ge_t<_Tp, _Up> { if (__lhs.has_value()) return *__lhs >= __rhs; return false; } template _REQUIRES_NOT_OPTIONAL(_Tp) constexpr auto operator>= [[nodiscard]] (const _Tp& __lhs, const optional<_Up>& __rhs) -> __optional_ge_t<_Tp, _Up> { if (__rhs.has_value()) return __lhs >= *__rhs; return true; } #ifdef __cpp_lib_three_way_comparison // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3746. optional's spaceship with U with a type derived from optional // causes infinite constraint meta-recursion template concept __is_derived_from_optional = requires (const _Tp& __t) { [](const optional<_Up>&){ }(__t); }; template requires (!__is_derived_from_optional<_Up>) && requires { typename compare_three_way_result_t<_Tp, _Up>; } && three_way_comparable_with<_Tp, _Up> constexpr compare_three_way_result_t<_Tp, _Up> operator<=> [[nodiscard]] (const optional<_Tp>& __x, const _Up& __v) { return bool(__x) ? *__x <=> __v : strong_ordering::less; } #endif // Swap and creation functions. // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2748. swappable traits for optionals template _GLIBCXX20_CONSTEXPR inline enable_if_t && is_swappable_v<_Tp>> swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) noexcept(noexcept(__lhs.swap(__rhs))) { __lhs.swap(__rhs); } #if __cpp_lib_optional >= 202506L // We deviate from standard, that do not declared separate swap overload // from optional. template constexpr void swap(optional<_Tp&>& __lhs, optional<_Tp&>& __rhs) noexcept { __lhs.swap(__rhs); } #endif // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2766. Swapping non-swappable types template enable_if_t && is_swappable_v<_Tp>)> swap(optional<_Tp>&, optional<_Tp>&) = delete; #if __cpp_lib_optional >= 202506L template #else template #endif constexpr enable_if_t, _Tp>, optional>> make_optional(_Tp&& __t) noexcept(is_nothrow_constructible_v>, _Tp>) { return optional>( std::forward<_Tp>(__t) ); } template constexpr enable_if_t, optional<_Tp>> make_optional(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>) { return optional<_Tp>( in_place, std::forward<_Args>(__args)... ); } template constexpr enable_if_t&, _Args...>, optional<_Tp>> make_optional(initializer_list<_Up> __il, _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) { return optional<_Tp>( in_place, __il, std::forward<_Args>(__args)... ); } // Hash. template> struct __optional_hash #if ! _GLIBCXX_INLINE_VERSION : public __hash_empty_base<_Up> #endif { #if __cplusplus < 202002L using result_type [[__deprecated__]] = size_t; using argument_type [[__deprecated__]] = optional<_Tp>; #endif 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 hash> // hash for optional is disabled because is_hash_enabled_for is false : public __conditional_t<__is_hash_enabled_for>, __optional_hash<_Tp>, __hash_not_enabled<_Tp>> { }; template struct __is_fast_hash>> : __is_fast_hash> { }; /// @} #if __cpp_deduction_guides >= 201606 template optional(_Tp) -> optional<_Tp>; #endif #ifdef __cpp_lib_optional_range_support // >= C++26 template inline constexpr bool ranges::enable_view> = true; #if __cpp_lib_optional >= 202506L // C++26 template constexpr bool ranges::enable_borrowed_range> = true; #endif template inline constexpr range_format format_kind> = range_format::disabled; #endif // __cpp_lib_optional_range_support #undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __cpp_lib_optional #endif // _GLIBCXX_OPTIONAL