123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- // 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_trivially_copyable_v<_Tp>
- && sizeof(_Tp) <= sizeof(long),
- _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
|