C++ 绑定泛型成员函数
有时我需要将一些成员函数绑定到它的调用对象,以便以相同的方式处理成员函数和非成员函数。例如(典型的回调示例): 嗯。成员回调的C++ 绑定泛型成员函数,c++,c++11,bind,variadic-templates,C++,C++11,Bind,Variadic Templates,有时我需要将一些成员函数绑定到它的调用对象,以便以相同的方式处理成员函数和非成员函数。例如(典型的回调示例): 嗯。成员回调的add()重载只将对象绑定到成员函数,因为回调有三个参数,所以我们使用三个占位符 但请考虑:如果回调有任意数量的参数?< /强> .BR> 换句话说,如果callback\u list类模板是用可变模板定义的,我该怎么办 template<typename... ARGS> class callback_list{ ... }; 模板 类回调_列表{…};
add()
重载只将对象绑定到成员函数,因为回调有三个参数,所以我们使用三个占位符
但请考虑:<强>如果回调有任意数量的参数?< /强> .BR> 换句话说,如果
callback\u list
类模板是用可变模板定义的,我该怎么办
template<typename... ARGS>
class callback_list{ ... };
模板
类回调_列表{…};
如何使用
std::bind()
调用点处已知的任何函数参数绑定变量函数,即使用未指定数量的占位符 要使用std::bind
,我们需要提供一定数量的占位符,这取决于回调函数参数的数量。我已经描述了一种方法,通过为占位符创建一个生成器,您可以做到这一点:
template<int> struct placeholder_template {};
占位符生成器和整数序列的代码,来自另一个答案:
template<int...> struct int_sequence {};
template<int N, int... Is> struct make_int_sequence
: make_int_sequence<N-1, N-1, Is...> {};
template<int... Is> struct make_int_sequence<0, Is...>
: int_sequence<Is...> {};
template<int> // begin with 0 here!
struct placeholder_template
{};
#include <functional>
#include <type_traits>
namespace std
{
template<int N>
struct is_placeholder< placeholder_template<N> >
: integral_constant<int, N+1> // the one is important
{};
}
template struct int_sequence{};
模板结构make_int_序列
:make_int_sequence{};
模板结构make_int_序列
:int_序列{};
模板//此处以0开头!
结构占位符模板
{};
#包括
#包括
名称空间标准
{
模板
结构是_占位符<占位符_模板>
:积分常数//一个很重要
{};
}
使用C++14,可以使用std::index\u sequence\u for
而不是自定义make\u int\u sequence
旁注:如果您想接受带有cv和ref限定符的成员函数,可以使用非常通用的“模式”,如
模板
无效添加(C&ref,T fun);
并通过SFINAE进行限制。这使您可以从这样一个函数指针(通过
tuple\u size
)推断参数的数量。相关吗@dyp LOL我已经检查过了,,但我还没有找到那条线。。。非常感谢。那么这个解决方案也可以工作,不是吗?@dyp是的,这个解决方案可以工作,我目前正在测试它,但我特别感兴趣的是std::bind()
,以及如何使它工作。我是将它标记为副本还是?谢谢,最后它工作了。只有一个问题:我不能将bind的结果(即std::bind()
返回的bind代理)分配给std::function
,这当然正常工作。这个绑定可以改变结果代理的签名,然后破坏转换吗?@Manu343726这不是我在我的游戏中正在做的吗?我不得不再次查看Std,看看它是否真的需要工作,但对我来说,这听起来像是一个库缺陷。您使用了哪种库实现?可以使用简化。此外,还可以使用std::integral_constant{}…
而不是placeholder_template{}…
。这样,我们就可以完全摆脱第三段代码@黑暗的拉贡。。。它是从积分常数导出的。我的理解是:是占位符
是一个映射T->X
的元函数,其中X
是从某个积分常量
派生的(“基本特征”)。因此,bind
检查每个参数是否是\u占位符N>0
。但我看不出是在哪里定义的
占位符(例如N==M
)。
template<int> struct placeholder_template {};
template<typename... Params>
class callback_list
{
public:
using callback_t = std::function<void(Params...)>;
//Overload for non-member handlers:
void add( const callback_t& handler )
{
_handlers.push_back( handler );
}
private:
//Overload for member handlers:
template<typename CLASS, int... Is>
void add( CLASS& object_ref ,
void(CLASS::*member_function)( Params... ) ,
int_sequence<Is...> )
{
using namespace std::placeholders;
_handlers.push_back( std::bind( member_function ,
std::ref( object_ref ) ,
placeholder_template<Is>{}...
)
);
}
public:
template<typename CLASS>
void add( CLASS& object_ref ,
void(CLASS::*member_function)( Params... ) )
{
add( object_ref, member_function,
make_int_sequence<sizeof...(Params)>{} );
}
template<typename... ARGS>
void operator()( ARGS&&... args )
{
for( auto& handler : _handlers )
handler( std::forward<ARGS>( args )... );
}
private:
std::vector<callback_t> _handlers;
};
template<int...> struct int_sequence {};
template<int N, int... Is> struct make_int_sequence
: make_int_sequence<N-1, N-1, Is...> {};
template<int... Is> struct make_int_sequence<0, Is...>
: int_sequence<Is...> {};
template<int> // begin with 0 here!
struct placeholder_template
{};
#include <functional>
#include <type_traits>
namespace std
{
template<int N>
struct is_placeholder< placeholder_template<N> >
: integral_constant<int, N+1> // the one is important
{};
}
template<class C, class T>
void add(C& ref, T fun);