| // 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/mofunc_impl.h | |
| * This is an internal header file, included by other library headers. | |
| * Do not attempt to use it directly. @headername{functional} | |
| */ | |
| #ifndef _GLIBCXX_MOF_CV | |
| # define _GLIBCXX_MOF_CV | |
| #endif | |
| #ifdef _GLIBCXX_MOF_REF | |
| # define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF | |
| #else | |
| # define _GLIBCXX_MOF_REF | |
| # define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV & | |
| #endif | |
| #define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| /** | |
| * @brief Polymorphic function wrapper. | |
| * @ingroup functors | |
| * @since C++23 | |
| * @headerfile functional | |
| * | |
| * The `std::move_only_function` class template is a call wrapper similar | |
| * to `std::function`, but does not require the stored target function | |
| * to be copyable. | |
| * | |
| * It also supports const-qualification, ref-qualification, and | |
| * no-throw guarantees. The qualifications and exception-specification | |
| * of the `move_only_function::operator()` member function are respected | |
| * when invoking the target function. | |
| */ | |
| template<typename _Res, typename... _ArgTypes, bool _Noex> | |
| class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV | |
| _GLIBCXX_MOF_REF noexcept(_Noex)> | |
| : _Mofunc_base | |
| { | |
| template<typename _Tp> | |
| using __callable | |
| = __conditional_t<_Noex, | |
| is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>, | |
| is_invocable_r<_Res, _Tp, _ArgTypes...>>; | |
| // [func.wrap.mov.con]/1 is-callable-from<VT> | |
| template<typename _Vt> | |
| static constexpr bool __is_callable_from | |
| = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>, | |
| __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>; | |
| public: | |
| using result_type = _Res; | |
| /// Creates an empty object. | |
| move_only_function() noexcept { } | |
| /// Creates an empty object. | |
| move_only_function(nullptr_t) noexcept { } | |
| /// Moves the target object, leaving the source empty. | |
| move_only_function(move_only_function&& __x) noexcept | |
| : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)), | |
| _M_invoke(std::__exchange(__x._M_invoke, nullptr)) | |
| { } | |
| /// Stores a target object initialized from the argument. | |
| template<typename _Fn, typename _Vt = decay_t<_Fn>> | |
| requires (!is_same_v<_Vt, move_only_function>) | |
| && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt> | |
| move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>()) | |
| { | |
| if constexpr (is_function_v<remove_pointer_t<_Vt>> | |
| || is_member_pointer_v<_Vt> | |
| || __is_move_only_function_v<_Vt>) | |
| { | |
| if (__f == nullptr) | |
| return; | |
| } | |
| _M_init<_Vt>(std::forward<_Fn>(__f)); | |
| _M_invoke = &_S_invoke<_Vt>; | |
| } | |
| /// Stores a target object initialized from the arguments. | |
| template<typename _Tp, typename... _Args> | |
| requires is_constructible_v<_Tp, _Args...> | |
| && __is_callable_from<_Tp> | |
| explicit | |
| move_only_function(in_place_type_t<_Tp>, _Args&&... __args) | |
| noexcept(_S_nothrow_init<_Tp, _Args...>()) | |
| : _M_invoke(&_S_invoke<_Tp>) | |
| { | |
| static_assert(is_same_v<decay_t<_Tp>, _Tp>); | |
| _M_init<_Tp>(std::forward<_Args>(__args)...); | |
| } | |
| /// Stores a target object initialized from the arguments. | |
| template<typename _Tp, typename _Up, typename... _Args> | |
| requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> | |
| && __is_callable_from<_Tp> | |
| explicit | |
| move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il, | |
| _Args&&... __args) | |
| noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>()) | |
| : _M_invoke(&_S_invoke<_Tp>) | |
| { | |
| static_assert(is_same_v<decay_t<_Tp>, _Tp>); | |
| _M_init<_Tp>(__il, std::forward<_Args>(__args)...); | |
| } | |
| /// Stores a new target object, leaving `x` empty. | |
| move_only_function& | |
| operator=(move_only_function&& __x) noexcept | |
| { | |
| _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x)); | |
| _M_invoke = std::__exchange(__x._M_invoke, nullptr); | |
| return *this; | |
| } | |
| /// Destroys the target object (if any). | |
| move_only_function& | |
| operator=(nullptr_t) noexcept | |
| { | |
| _Mofunc_base::operator=(nullptr); | |
| _M_invoke = nullptr; | |
| return *this; | |
| } | |
| /// Stores a new target object, initialized from the argument. | |
| template<typename _Fn> | |
| requires is_constructible_v<move_only_function, _Fn> | |
| move_only_function& | |
| operator=(_Fn&& __f) | |
| noexcept(is_nothrow_constructible_v<move_only_function, _Fn>) | |
| { | |
| move_only_function(std::forward<_Fn>(__f)).swap(*this); | |
| return *this; | |
| } | |
| ~move_only_function() = default; | |
| /// True if a target object is present, false otherwise. | |
| explicit operator bool() const noexcept { return _M_invoke != nullptr; } | |
| /** Invoke the target object. | |
| * | |
| * The target object will be invoked using the supplied arguments, | |
| * and as an lvalue or rvalue, and as const or non-const, as dictated | |
| * by the template arguments of the `move_only_function` specialization. | |
| * | |
| * @pre Must not be empty. | |
| */ | |
| _Res | |
| operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex) | |
| { | |
| __glibcxx_assert(*this != nullptr); | |
| return _M_invoke(this, std::forward<_ArgTypes>(__args)...); | |
| } | |
| /// Exchange the target objects (if any). | |
| void | |
| swap(move_only_function& __x) noexcept | |
| { | |
| _Mofunc_base::swap(__x); | |
| std::swap(_M_invoke, __x._M_invoke); | |
| } | |
| /// Exchange the target objects (if any). | |
| friend void | |
| swap(move_only_function& __x, move_only_function& __y) noexcept | |
| { __x.swap(__y); } | |
| /// Check for emptiness by comparing with `nullptr`. | |
| friend bool | |
| operator==(const move_only_function& __x, nullptr_t) noexcept | |
| { return __x._M_invoke == nullptr; } | |
| private: | |
| template<typename _Tp> | |
| using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>; | |
| using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*, | |
| __param_t<_ArgTypes>...) noexcept(_Noex); | |
| template<typename _Tp> | |
| static _Res | |
| _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self, | |
| __param_t<_ArgTypes>... __args) noexcept(_Noex) | |
| { | |
| using _TpCv = _Tp _GLIBCXX_MOF_CV; | |
| using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS; | |
| return std::__invoke_r<_Res>( | |
| std::forward<_TpInv>(*_S_access<_TpCv>(__self)), | |
| std::forward<__param_t<_ArgTypes>>(__args)...); | |
| } | |
| _Invoker _M_invoke = nullptr; | |
| }; | |
| #undef _GLIBCXX_MOF_CV_REF | |
| #undef _GLIBCXX_MOF_CV | |
| #undef _GLIBCXX_MOF_REF | |
| #undef _GLIBCXX_MOF_INV_QUALS | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace std |