| // Implementation of std::move_only_function -*- C++ -*- | |
| // 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/bits/move_only_function.h | |
| * This is an internal header file, included by other library headers. | |
| * Do not attempt to use it directly. @headername{functional} | |
| */ | |
| #ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H | |
| #define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1 | |
| #ifdef _GLIBCXX_SYSHDR | |
| #pragma GCC system_header | |
| #endif | |
| #include <bits/version.h> | |
| #ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED | |
| #include <bits/invoke.h> | |
| #include <bits/utility.h> | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| template<typename... _Signature> | |
| class move_only_function; // not defined | |
| /// @cond undocumented | |
| class _Mofunc_base | |
| { | |
| protected: | |
| _Mofunc_base() noexcept | |
| : _M_manage(_S_empty) | |
| { } | |
| _Mofunc_base(_Mofunc_base&& __x) noexcept | |
| { | |
| _M_manage = std::__exchange(__x._M_manage, _S_empty); | |
| _M_manage(_M_storage, &__x._M_storage); | |
| } | |
| template<typename _Tp, typename... _Args> | |
| static constexpr bool | |
| _S_nothrow_init() noexcept | |
| { | |
| if constexpr (__stored_locally<_Tp>) | |
| return is_nothrow_constructible_v<_Tp, _Args...>; | |
| return false; | |
| } | |
| template<typename _Tp, typename... _Args> | |
| void | |
| _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>()) | |
| { | |
| if constexpr (__stored_locally<_Tp>) | |
| ::new (_M_storage._M_addr()) _Tp(std::forward<_Args>(__args)...); | |
| else | |
| _M_storage._M_p = new _Tp(std::forward<_Args>(__args)...); | |
| _M_manage = &_S_manage<_Tp>; | |
| } | |
| _Mofunc_base& | |
| operator=(_Mofunc_base&& __x) noexcept | |
| { | |
| _M_manage(_M_storage, nullptr); | |
| _M_manage = std::__exchange(__x._M_manage, _S_empty); | |
| _M_manage(_M_storage, &__x._M_storage); | |
| return *this; | |
| } | |
| _Mofunc_base& | |
| operator=(nullptr_t) noexcept | |
| { | |
| _M_manage(_M_storage, nullptr); | |
| _M_manage = _S_empty; | |
| return *this; | |
| } | |
| ~_Mofunc_base() { _M_manage(_M_storage, nullptr); } | |
| void | |
| swap(_Mofunc_base& __x) noexcept | |
| { | |
| // Order of operations here is more efficient if __x is empty. | |
| _Storage __s; | |
| __x._M_manage(__s, &__x._M_storage); | |
| _M_manage(__x._M_storage, &_M_storage); | |
| __x._M_manage(_M_storage, &__s); | |
| std::swap(_M_manage, __x._M_manage); | |
| } | |
| template<typename _Tp, typename _Self> | |
| static _Tp* | |
| _S_access(_Self* __self) noexcept | |
| { | |
| if constexpr (__stored_locally<remove_const_t<_Tp>>) | |
| return static_cast<_Tp*>(__self->_M_storage._M_addr()); | |
| else | |
| return static_cast<_Tp*>(__self->_M_storage._M_p); | |
| } | |
| private: | |
| struct _Storage | |
| { | |
| void* _M_addr() noexcept { return &_M_bytes[0]; } | |
| const void* _M_addr() const noexcept { return &_M_bytes[0]; } | |
| // We want to have enough space to store a simple delegate type. | |
| struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; }; | |
| union { | |
| void* _M_p; | |
| alignas(_Delegate) alignas(void(*)()) | |
| unsigned char _M_bytes[sizeof(_Delegate)]; | |
| }; | |
| }; | |
| template<typename _Tp> | |
| static constexpr bool __stored_locally | |
| = sizeof(_Tp) <= sizeof(_Storage) && alignof(_Tp) <= alignof(_Storage) | |
| && is_nothrow_move_constructible_v<_Tp>; | |
| // A function that either destroys the target object stored in __target, | |
| // or moves the target object from *__src to __target. | |
| using _Manager = void (*)(_Storage& __target, _Storage* __src) noexcept; | |
| // The no-op manager function for objects with no target. | |
| static void _S_empty(_Storage&, _Storage*) noexcept { } | |
| // The real manager function for a target object of type _Tp. | |
| template<typename _Tp> | |
| static void | |
| _S_manage(_Storage& __target, _Storage* __src) noexcept | |
| { | |
| if constexpr (__stored_locally<_Tp>) | |
| { | |
| if (__src) | |
| { | |
| _Tp* __rval = static_cast<_Tp*>(__src->_M_addr()); | |
| ::new (__target._M_addr()) _Tp(std::move(*__rval)); | |
| __rval->~_Tp(); | |
| } | |
| else | |
| static_cast<_Tp*>(__target._M_addr())->~_Tp(); | |
| } | |
| else | |
| { | |
| if (__src) | |
| __target._M_p = __src->_M_p; | |
| else | |
| delete static_cast<_Tp*>(__target._M_p); | |
| } | |
| } | |
| _Storage _M_storage; | |
| _Manager _M_manage; | |
| }; | |
| template<typename _Tp> | |
| inline constexpr bool __is_move_only_function_v = false; | |
| template<typename _Tp> | |
| constexpr bool __is_move_only_function_v<move_only_function<_Tp>> = true; | |
| /// @endcond | |
| namespace __detail::__variant | |
| { | |
| template<typename> struct _Never_valueless_alt; // see <variant> | |
| // Provide the strong exception-safety guarantee when emplacing a | |
| // move_only_function into a variant. | |
| template<typename... _Signature> | |
| struct _Never_valueless_alt<std::move_only_function<_Signature...>> | |
| : true_type | |
| { }; | |
| } // namespace __detail::__variant | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace std | |
| #include "mofunc_impl.h" | |
| #define _GLIBCXX_MOF_CV const | |
| #include "mofunc_impl.h" | |
| #define _GLIBCXX_MOF_REF & | |
| #include "mofunc_impl.h" | |
| #define _GLIBCXX_MOF_REF && | |
| #include "mofunc_impl.h" | |
| #define _GLIBCXX_MOF_CV const | |
| #define _GLIBCXX_MOF_REF & | |
| #include "mofunc_impl.h" | |
| #define _GLIBCXX_MOF_CV const | |
| #define _GLIBCXX_MOF_REF && | |
| #include "mofunc_impl.h" | |
| #endif // __glibcxx_move_only_function | |
| #endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H |