funcref_impl.h
Go to the documentation of this file.
// Implementation of std::function_ref -*- 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/funcref_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
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
namespace __polyfunc
{
template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV
noexcept(_Noex)>
{ using type = _Ret(_Args...) noexcept(_Noex); };
template<bool _Noex, typename _Ret, typename _Class, typename... _Args>
struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV&
noexcept(_Noex)>
{ using type = _Ret(_Args...) noexcept(_Noex); };
} // namespace __polyfunc
/// @endcond
/**
* @brief Non-owning polymorphic function wrapper.
* @ingroup functors
* @since C++26
* @headerfile functional
*
* The `std::function_ref` class template is a non-owning call wrapper,
* that refers to a bound object. Using function_ref outside of the lifetime
* of the bound object has undefined behavior.
*
* It supports const-qualification and no-throw guarantees. The
* qualifications and exception-specification of the signature are respected
* when invoking the reference function.
*/
template<typename _Res, typename... _ArgTypes, bool _Noex>
class function_ref<_Res(_ArgTypes...) _GLIBCXX_MOF_CV
noexcept(_Noex)>
{
static_assert(
(std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...),
"each parameter type must be a complete class");
using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>;
using _Signature = _Invoker::_Signature;
// [func.wrap.ref.ctor]/1 is-invokable-using
template<typename... _Tps>
static constexpr bool __is_invocable_using
= __conditional_t<_Noex,
is_nothrow_invocable_r<_Res, _Tps..., _ArgTypes...>,
is_invocable_r<_Res, _Tps..., _ArgTypes...>>::value;
public:
/// Target and bound object is function pointed by parameter.
template<typename _Fn>
requires is_function_v<_Fn> && __is_invocable_using<_Fn*>
function_ref(_Fn* __fn) noexcept
{
__glibcxx_assert(__fn != nullptr);
_M_invoke = _Invoker::template _S_ptrs<_Fn*>();
_M_init(__fn);
}
/// Target and bound object is object referenced by parameter.
template<typename _Fn, typename _Vt = remove_reference_t<_Fn>>
requires (!is_same_v<remove_cv_t<_Vt>, function_ref>)
&& (!is_member_pointer_v<_Vt>)
// We deviate from standard by having this condition, that forces
// function references to use _Fn* constructors. This simplies
// implementation and provide better diagnostic when used in
// constant expression (above constructor is not constexpr).
&& (!is_function_v<_Vt>)
&& __is_invocable_using<_Vt _GLIBCXX_MOF_CV&>
constexpr
function_ref(_Fn&& __f) noexcept
{
using _Fd = remove_cv_t<_Vt>;
if constexpr (__is_std_op_wrapper<_Fd>)
{
_M_invoke = _Invoker::template _S_nttp<_Fd{}>;
_M_ptrs._M_obj = nullptr;
}
else if constexpr (requires (_ArgTypes&&... __args) {
_Fd::operator()(std::forward<_ArgTypes>(__args)...);
})
{
_M_invoke = _Invoker::template _S_static<_Fd>;
_M_ptrs._M_obj = nullptr;
}
else
{
_M_invoke = _Invoker::template _S_ptrs<_Vt _GLIBCXX_MOF_CV&>();
_M_init(std::addressof(__f));
}
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 4256. Incorrect constrains for function_ref constructors from nontype
/// Target object is __fn. There is no bound object.
template<auto __cwfn, typename _Fn>
requires __is_invocable_using<const _Fn&>
constexpr
function_ref(constant_wrapper<__cwfn, _Fn>) noexcept
{
constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
if constexpr (sizeof...(_ArgTypes) > 0)
if constexpr ((... && _ConstExprParam<remove_cvref_t<_ArgTypes>>))
static_assert(!requires {
typename constant_wrapper<
std::__invoke(__fn, remove_cvref_t<_ArgTypes>::value...)>;
}, "cw<fn>(args...) should be equivalent to fn(args...)");
if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
static_assert(__fn != nullptr);
_M_invoke = &_Invoker::template _S_nttp<__fn>;
_M_ptrs._M_obj = nullptr;
}
/// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
/// Bound object is object referenced by second parameter.
template<auto __cwfn, typename _Fn, typename _Up,
typename _Td = remove_reference_t<_Up>>
requires (!is_rvalue_reference_v<_Up&&>)
&& __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV&>
constexpr
function_ref(constant_wrapper<__cwfn, _Fn>, _Up&& __ref) noexcept
{
constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
static_assert(__fn != nullptr);
if constexpr (is_member_pointer_v<_Fn>
&& same_as<_Td, typename __inv_unwrap<_Td>::type>)
// N.B. invoking member pointer on lvalue produces the same effects,
// as invoking it on pointer to that lvalue.
_M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
else
_M_invoke = &_Invoker::template _S_bind_ref<__fn, _Td _GLIBCXX_MOF_CV&>;
_M_init(std::addressof(__ref));
}
/// Target object is equivalent to std::bind_front<_fn>(__ptr).
/// Bound object is object pointed by second parameter (if any).
template< auto __cwfn, typename _Fn, typename _Td>
requires __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV*>
constexpr
function_ref(constant_wrapper<__cwfn, _Fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept
{
constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
static_assert(__fn != nullptr);
if constexpr (is_member_pointer_v<_Fn>)
__glibcxx_assert(__ptr != nullptr);
_M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>;
_M_init(__ptr);
}
template<typename _Tp>
requires (!is_same_v<_Tp, function_ref>) && (!is_pointer_v<_Tp>)
&& (!__is_constant_wrapper_v<_Tp>)
function_ref&
operator=(_Tp) = delete;
/** Invoke the target object.
*
* The bound object will be invoked using the supplied arguments,
* and as const or non-const, as dictated by the template arguments
* of the `function_ref` specialization.
*/
_Res
operator()(_ArgTypes... __args) const noexcept(_Noex)
{ return _M_invoke(_M_ptrs, std::forward<_ArgTypes>(__args)...); }
private:
template<typename _Tp>
constexpr void
_M_init(_Tp* __ptr) noexcept
{
if constexpr (is_function_v<_Tp>)
_M_ptrs._M_func = reinterpret_cast<void(*)()>(__ptr);
else
_M_ptrs._M_obj = __ptr;
}
typename _Invoker::__ptrs_func_t _M_invoke;
__polyfunc::_Ptrs _M_ptrs;
};
#undef _GLIBCXX_MOF_CV
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
std::remove_reference_t
typename remove_reference< _Tp >::type remove_reference_t
Alias template for remove_reference.
Definition type_traits:1890
std::addressof
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition move.h:176
std::__invoke
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition invoke.h:92
std::forward
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
std
ISO C++ entities toplevel namespace is std.
std::function_ref< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::function_ref
constexpr function_ref(_Fn &&__f) noexcept
Target and bound object is object referenced by parameter.
Definition funcref_impl.h:107
std::function_ref< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::function_ref
function_ref(_Fn *__fn) noexcept
Target and bound object is function pointed by parameter.
Definition funcref_impl.h:89
std::function_ref< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::function_ref
constexpr function_ref(constant_wrapper< __cwfn, _Fn >, _Td _GLIBCXX_MOF_CV *__ptr) noexcept
Target object is equivalent to std::bind_front<_fn>(__ptr). Bound object is object pointed by second ...
Definition funcref_impl.h:180
std::function_ref< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::function_ref
constexpr function_ref(constant_wrapper< __cwfn, _Fn >) noexcept
Target object is __fn. There is no bound object.
Definition funcref_impl.h:135
std::function_ref< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::operator()
_Res operator()(_ArgTypes... __args) const noexcept(_Noex)
Definition funcref_impl.h:205
std::function_ref< _Res(_ArgTypes...) _GLIBCXX_MOF_CV noexcept(_Noex)>::function_ref
constexpr function_ref(constant_wrapper< __cwfn, _Fn >, _Up &&__ref) noexcept
Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)). Bound object is object referenc...
Definition funcref_impl.h:159
std::same_as
[concept.same], concept same_as
Definition concepts:65