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);