diff options
author | alk3pInjection <webmaster@raspii.tech> | 2024-02-04 16:16:35 +0800 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2024-02-04 16:16:35 +0800 |
commit | 6ce4ebed87858ecdd79a1091367c6e961055daa9 (patch) | |
tree | 1c2a6a60531acf791531bbd9c8ac14c23ef8a66c /aarch64-none-linux-gnu/include/c++/13.2.1/optional |
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
Change-Id: I7303388733328cd98ab9aa3c30236db67f2e9e9c
Diffstat (limited to 'aarch64-none-linux-gnu/include/c++/13.2.1/optional')
-rw-r--r-- | aarch64-none-linux-gnu/include/c++/13.2.1/optional | 1512 |
1 files changed, 1512 insertions, 0 deletions
diff --git a/aarch64-none-linux-gnu/include/c++/13.2.1/optional b/aarch64-none-linux-gnu/include/c++/13.2.1/optional new file mode 100644 index 0000000..bcac152 --- /dev/null +++ b/aarch64-none-linux-gnu/include/c++/13.2.1/optional @@ -0,0 +1,1512 @@ +// <optional> -*- C++ -*- + +// Copyright (C) 2013-2023 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 +// <http://www.gnu.org/licenses/>. + +/** @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 <type_traits> +#include <exception> +#include <new> +#include <initializer_list> +#include <bits/enable_special_members.h> +#include <bits/exception_defines.h> +#include <bits/functional_hash.h> +#include <bits/stl_construct.h> // _Construct +#include <bits/utility.h> // in_place_t +#if __cplusplus > 201703L +# include <compare> +# include <bits/invoke.h> // std::__invoke +#endif +#if __cplusplus > 202002L +# include <concepts> +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#if __cplusplus > 202002L && __cpp_lib_concepts +# define __cpp_lib_optional 202110L +#elif __cplusplus >= 202002L +# define __cpp_lib_optional 202106L +#else +# define __cpp_lib_optional 201606L +#endif + + template<typename _Tp> + 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<typename _Fn> 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 <typename _Tp> + struct _Optional_payload_base + { + using _Stored_type = remove_const_t<_Tp>; + + _Optional_payload_base() = default; + ~_Optional_payload_base() = default; + + template<typename... _Args> + constexpr + _Optional_payload_base(in_place_t __tag, _Args&&... __args) + : _M_payload(__tag, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + template<typename _Up, typename... _Args> + 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_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(); + } + } + + struct _Empty_byte { }; + + template<typename _Up, bool = is_trivially_destructible_v<_Up>> + union _Storage + { + constexpr _Storage() noexcept : _M_empty() { } + + template<typename... _Args> + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template<typename _Vp, typename... _Args> + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + +#if __cplusplus >= 202002L + template<typename _Fn, typename _Arg> + constexpr + _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) + : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), + std::forward<_Arg>(__arg))) + { } +#endif + + _Empty_byte _M_empty; + _Up _M_value; + }; + + template<typename _Up> + union _Storage<_Up, false> + { + constexpr _Storage() noexcept : _M_empty() { } + + template<typename... _Args> + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template<typename _Vp, typename... _Args> + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + +#if __cplusplus >= 202002L + template<typename _Fn, typename _Arg> + 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() { } + + _Empty_byte _M_empty; + _Up _M_value; + }; + + _Storage<_Stored_type> _M_payload; + + bool _M_engaged = false; + + template<typename... _Args> + 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<typename _Fn, typename _Up> + 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(); + } + }; + + // Class template that manages the payload for optionals. + template <typename _Tp, + bool /*_HasTrivialDestructor*/ = + is_trivially_destructible_v<_Tp>, + 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 <typename _Tp> + 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 <typename _Tp> + 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 <typename _Tp> + 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_constructible<_Tp>, + 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 <typename _Tp> + 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_constructible<_Tp>, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial destructors. + template <typename _Tp, bool _Copy, bool _Move> + 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(); } + }; + + // Common base class for _Optional_base<T> to avoid repeating these + // member functions in each specialization. + template<typename _Tp, typename _Dp> + 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<typename... _Args> + 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<const _Dp*>(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 static_cast<_Dp*>(this)->_M_payload._M_get(); + } + + constexpr const _Tp& + _M_get() const noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast<const _Dp*>(this)->_M_payload._M_get(); + } + }; + + /** + * @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<typename _Tp, + bool = is_trivially_copy_constructible_v<_Tp>, + bool = is_trivially_move_constructible_v<_Tp>> + struct _Optional_base + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template<typename... _Args, + enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template<typename _Up, typename... _Args, + enable_if_t<is_constructible_v<_Tp, + initializer_list<_Up>&, + _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_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<typename _Tp> + struct _Optional_base<_Tp, false, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template<typename... _Args, + enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template<typename _Up, typename... _Args, + enable_if_t<is_constructible_v<_Tp, + initializer_list<_Up>&, + _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<typename _Tp> + struct _Optional_base<_Tp, true, false> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template<typename... _Args, + enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template<typename _Up, typename... _Args, + enable_if_t<is_constructible_v<_Tp, + initializer_list<_Up>&, + _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<typename _Tp> + struct _Optional_base<_Tp, true, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template<typename... _Args, + enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> + constexpr explicit + _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, std::forward<_Args>(__args)...) + { } + + template<typename _Up, typename... _Args, + enable_if_t<is_constructible_v<_Tp, + initializer_list<_Up>&, + _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; + }; + + template<typename _Tp> + class optional; + + template<typename _Tp> + inline constexpr bool __is_optional_v = false; + template<typename _Tp> + inline constexpr bool __is_optional_v<optional<_Tp>> = true; + + template<typename _Tp, typename _Up> + using __converts_from_optional = + __or_<is_constructible<_Tp, const optional<_Up>&>, + is_constructible<_Tp, optional<_Up>&>, + is_constructible<_Tp, const optional<_Up>&&>, + is_constructible<_Tp, optional<_Up>&&>, + is_convertible<const optional<_Up>&, _Tp>, + is_convertible<optional<_Up>&, _Tp>, + is_convertible<const optional<_Up>&&, _Tp>, + is_convertible<optional<_Up>&&, _Tp>>; + + template<typename _Tp, typename _Up> + using __assigns_from_optional = + __or_<is_assignable<_Tp&, const optional<_Up>&>, + is_assignable<_Tp&, optional<_Up>&>, + is_assignable<_Tp&, const optional<_Up>&&>, + is_assignable<_Tp&, optional<_Up>&&>>; + + /** + * @brief Class template for optional values. + */ + template<typename _Tp> + class optional + : private _Optional_base<_Tp>, + private _Enable_copy_move< + // Copy constructor. + is_copy_constructible_v<_Tp>, + // Copy assignment. + __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>, + // Move constructor. + is_move_constructible_v<_Tp>, + // Move assignment. + __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>, + // Unique tag type. + optional<_Tp>> + { + static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>); + static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>); + static_assert(is_object_v<_Tp> && !is_array_v<_Tp>); + + private: + using _Base = _Optional_base<_Tp>; + + // SFINAE helpers + template<typename _Up> + using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>; + template<typename _Up> + using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>; + template<typename... _Cond> + using _Requires = enable_if_t<__and_v<_Cond...>, bool>; + + public: + using value_type = _Tp; + + constexpr optional() noexcept { } + + constexpr optional(nullopt_t) noexcept { } + + // Converting constructors for engaged optionals. + template<typename _Up = _Tp, + _Requires<__not_self<_Up>, __not_tag<_Up>, + is_constructible<_Tp, _Up>, + is_convertible<_Up, _Tp>> = true> + constexpr + optional(_Up&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template<typename _Up = _Tp, + _Requires<__not_self<_Up>, __not_tag<_Up>, + is_constructible<_Tp, _Up>, + __not_<is_convertible<_Up, _Tp>>> = false> + explicit constexpr + optional(_Up&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template<typename _Up, + _Requires<__not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, const _Up&>, + is_convertible<const _Up&, _Tp>, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(const optional<_Up>& __t) + noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) + { + if (__t) + emplace(*__t); + } + + template<typename _Up, + _Requires<__not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, const _Up&>, + __not_<is_convertible<const _Up&, _Tp>>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(const optional<_Up>& __t) + noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) + { + if (__t) + emplace(*__t); + } + + template<typename _Up, + _Requires<__not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, _Up>, + is_convertible<_Up, _Tp>, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(optional<_Up>&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + { + if (__t) + emplace(std::move(*__t)); + } + + template<typename _Up, + _Requires<__not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, _Up>, + __not_<is_convertible<_Up, _Tp>>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(optional<_Up>&& __t) + noexcept(is_nothrow_constructible_v<_Tp, _Up>) + { + if (__t) + emplace(std::move(*__t)); + } + + template<typename... _Args, + _Requires<is_constructible<_Tp, _Args...>> = 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<typename _Up, typename... _Args, + _Requires<is_constructible<_Tp, + initializer_list<_Up>&, + _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)...) { } + + + // Assignment operators. + _GLIBCXX20_CONSTEXPR optional& + operator=(nullopt_t) noexcept + { + this->_M_reset(); + return *this; + } + + template<typename _Up = _Tp> + _GLIBCXX20_CONSTEXPR + enable_if_t<__and_v<__not_self<_Up>, + __not_<__and_<is_scalar<_Tp>, + is_same<_Tp, decay_t<_Up>>>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>, + optional&> + operator=(_Up&& __u) + noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>, + 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<typename _Up> + _GLIBCXX20_CONSTEXPR + enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, const _Up&>, + is_assignable<_Tp&, const _Up&>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(const optional<_Up>& __u) + noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>, + is_nothrow_assignable<_Tp&, const _Up&>>) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = *__u; + else + this->_M_construct(*__u); + } + else + { + this->_M_reset(); + } + return *this; + } + + template<typename _Up> + _GLIBCXX20_CONSTEXPR + enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(optional<_Up>&& __u) + noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>, + is_nothrow_assignable<_Tp&, _Up>>) + { + 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<typename... _Args> + _GLIBCXX20_CONSTEXPR + enable_if_t<is_constructible_v<_Tp, _Args...>, _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<typename _Up, typename... _Args> + _GLIBCXX20_CONSTEXPR + enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _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(); + } + } + + // Observers. + constexpr const _Tp* + operator->() const noexcept + { return std::__addressof(this->_M_get()); } + + constexpr _Tp* + operator->() noexcept + { return std::__addressof(this->_M_get()); } + + constexpr const _Tp& + operator*() const& noexcept + { return this->_M_get(); } + + constexpr _Tp& + operator*()& noexcept + { return this->_M_get(); } + + constexpr _Tp&& + operator*()&& noexcept + { return std::move(this->_M_get()); } + + constexpr const _Tp&& + operator*() const&& noexcept + { 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(); + } + + template<typename _Up> + constexpr _Tp + value_or(_Up&& __u) const& + { + static_assert(is_copy_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + if (this->_M_is_engaged()) + return this->_M_get(); + else + return static_cast<_Tp>(std::forward<_Up>(__u)); + } + + template<typename _Up> + constexpr _Tp + value_or(_Up&& __u) && + { + static_assert(is_move_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + if (this->_M_is_engaged()) + return std::move(this->_M_get()); + else + return static_cast<_Tp>(std::forward<_Up>(__u)); + } + +#if __cpp_lib_optional >= 202110L + // [optional.monadic] + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) & + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>; + static_assert(__is_optional_v<remove_cvref_t<_Up>>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), **this); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) const & + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp&>>; + static_assert(__is_optional_v<_Up>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), **this); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) && + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>; + static_assert(__is_optional_v<remove_cvref_t<_Up>>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + and_then(_Fn&& __f) const && + { + using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>; + static_assert(__is_optional_v<remove_cvref_t<_Up>>); + if (has_value()) + return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); + else + return _Up(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) & + { + using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, **this); + else + return optional<_Up>(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) const & + { + using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp&>>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, **this); + else + return optional<_Up>(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) && + { + using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp>>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); + else + return optional<_Up>(); + } + + template<typename _Fn> + constexpr auto + transform(_Fn&& __f) const && + { + using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp>>; + if (has_value()) + return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); + else + return optional<_Up>(); + } + + template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp> + constexpr optional + or_else(_Fn&& __f) const& + { + using _Up = invoke_result_t<_Fn>; + static_assert( is_same_v<remove_cvref_t<_Up>, optional> ); + + if (has_value()) + return *this; + else + return std::forward<_Fn>(__f)(); + } + + template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp> + constexpr optional + or_else(_Fn&& __f) && + { + using _Up = invoke_result_t<_Fn>; + static_assert( is_same_v<remove_cvref_t<_Up>, optional> ); + + if (has_value()) + return std::move(*this); + else + return std::forward<_Fn>(__f)(); + } +#endif + + _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); } + + private: +#if __cplusplus >= 202002L + template<typename _Up> friend class optional; + + template<typename _Fn, typename _Value> + explicit constexpr + optional(_Optional_func<_Fn> __f, _Value&& __v) + { + this->_M_payload._M_apply(__f, std::forward<_Value>(__v)); + } +#endif + }; + + template<typename _Tp> + using __optional_relop_t = + enable_if_t<is_convertible<_Tp, bool>::value, bool>; + + template<typename _Tp, typename _Up> + using __optional_eq_t = __optional_relop_t< + decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()) + >; + + template<typename _Tp, typename _Up> + using __optional_ne_t = __optional_relop_t< + decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()) + >; + + template<typename _Tp, typename _Up> + using __optional_lt_t = __optional_relop_t< + decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()) + >; + + template<typename _Tp, typename _Up> + using __optional_gt_t = __optional_relop_t< + decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()) + >; + + template<typename _Tp, typename _Up> + using __optional_le_t = __optional_relop_t< + decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()) + >; + + template<typename _Tp, typename _Up> + using __optional_ge_t = __optional_relop_t< + decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()) + >; + + // Comparisons between optional values. + template<typename _Tp, typename _Up> + constexpr auto + operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_eq_t<_Tp, _Up> + { + return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) + && (!__lhs || *__lhs == *__rhs); + } + + template<typename _Tp, typename _Up> + constexpr auto + operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_ne_t<_Tp, _Up> + { + return static_cast<bool>(__lhs) != static_cast<bool>(__rhs) + || (static_cast<bool>(__lhs) && *__lhs != *__rhs); + } + + template<typename _Tp, typename _Up> + constexpr auto + operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_lt_t<_Tp, _Up> + { + return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); + } + + template<typename _Tp, typename _Up> + constexpr auto + operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_gt_t<_Tp, _Up> + { + return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs); + } + + template<typename _Tp, typename _Up> + constexpr auto + operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_le_t<_Tp, _Up> + { + return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs); + } + + template<typename _Tp, typename _Up> + constexpr auto + operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_ge_t<_Tp, _Up> + { + return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs); + } + +#ifdef __cpp_lib_three_way_comparison + template<typename _Tp, three_way_comparable_with<_Tp> _Up> + 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<typename _Tp> + constexpr bool + operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + +#ifdef __cpp_lib_three_way_comparison + template<typename _Tp> + constexpr strong_ordering + operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept + { return bool(__x) <=> false; } +#else + 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; } +#endif // three-way-comparison + + // Comparisons with value type. + template<typename _Tp, typename _Up> + constexpr auto + operator==(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_eq_t<_Tp, _Up> + { return __lhs && *__lhs == __rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator==(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_eq_t<_Up, _Tp> + { return __rhs && __lhs == *__rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_ne_t<_Tp, _Up> + { return !__lhs || *__lhs != __rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_ne_t<_Up, _Tp> + { return !__rhs || __lhs != *__rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator<(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_lt_t<_Tp, _Up> + { return !__lhs || *__lhs < __rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator<(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_lt_t<_Up, _Tp> + { return __rhs && __lhs < *__rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator>(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_gt_t<_Tp, _Up> + { return __lhs && *__lhs > __rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator>(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_gt_t<_Up, _Tp> + { return !__rhs || __lhs > *__rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_le_t<_Tp, _Up> + { return !__lhs || *__lhs <= __rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_le_t<_Up, _Tp> + { return __rhs && __lhs <= *__rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_ge_t<_Tp, _Up> + { return __lhs && *__lhs >= __rhs; } + + template<typename _Tp, typename _Up> + constexpr auto + operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_ge_t<_Up, _Tp> + { return !__rhs || __lhs >= *__rhs; } + +#ifdef __cpp_lib_three_way_comparison + template<typename _Tp, typename _Up> + requires (!__is_optional_v<_Up>) + && three_way_comparable_with<_Tp, _Up> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(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<typename _Tp> + _GLIBCXX20_CONSTEXPR + inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>> + swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template<typename _Tp> + enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)> + swap(optional<_Tp>&, optional<_Tp>&) = delete; + + template<typename _Tp> + constexpr + enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>, + optional<decay_t<_Tp>>> + make_optional(_Tp&& __t) + noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>) + { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; } + + template<typename _Tp, typename... _Args> + constexpr + enable_if_t<is_constructible_v<_Tp, _Args...>, + optional<_Tp>> + make_optional(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) + { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; } + + template<typename _Tp, typename _Up, typename... _Args> + constexpr + enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _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<typename _Tp, typename _Up = remove_const_t<_Tp>, + 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<size_t>(-3333); + return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; + } + }; + + template<typename _Tp, typename _Up> + struct __optional_hash_call_base<_Tp, _Up, false> {}; + + template<typename _Tp> + struct hash<optional<_Tp>> + : private __poison_hash<remove_const_t<_Tp>>, + public __optional_hash_call_base<_Tp> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = optional<_Tp>; + }; + + template<typename _Tp> + struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>> + { }; + + /// @} + +#if __cpp_deduction_guides >= 201606 + template <typename _Tp> optional(_Tp) -> optional<_Tp>; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_OPTIONAL |