Sometimes I need to bind some member functions to its calling object, to treat member functions and non-member functions in the same homogeneous way. For example (The tipical callback example):
#include <vector>
#include <functional>
void f(int){}
struct foo
{
void f(int){}
};
int main()
{
using namespace std::placeholders;
foo my_foo;
std::vector<std::function<void()>> functions;
functions.push_back( f );
functions.push_back([](int){});
functions.push_back( std::bind( &foo::f , my_foo , _1 ) );
for( auto& function : functions )
{
function(0);
}
}
As more parameters the member function has, more placeholders we need to put inside the std::bind()
call.
Now consider a generic version of that. There shouldn't be problem, isn't?:
#include <vector>
#include <functional>
void f(int){}
struct foo
{
void f(int){}
};
template<typename FIRST , typename SECOND , typename THIRD>
class callback_list
{
using callback_t = std::function<void(FIRST,SECOND,THIRD>)>;
//Overload for non-member handlers:
void add( const callback_t& handler )
{
_handlers.push_back( handler );
}
//Overload for member handlers:
template<typename CLASS>
void add( CLASS& object_ref ,
void(CLASS::*member_function)( FIRST,SECOND,THIRD ) )
{
using namespace std::placeholders;
_handlers.push_back( std::bind( member_function ,
std::ref( object_ref ) ,
_1 , _2 , _3
)
);
}
template<typename... ARGS>
void operator()( ARGS&&... args )
{
for( auto& handler : _handlers )
handler( std::forward<ARGS>( args )... );
}
private:
std::vector<callback_t> functions;
};
void f(int,int,int){}
struct foo
{
void f(int,int,int){}
};
int main()
{
using namespace std::placeholders;
foo my_foo;
callback_list<int,int,int> callbacks;
callbacks.add( f );
callbacks.add([](int,int,int){});
callbacks.add( my_foo , &foo::f );
callbacks(0,0,0);
}
Ok. The add()
overload for member callbacks just binds the object to the member function, and because the callbacks are of three parameters, we use three placeholders.
But consider this: What if the callbacks have any number of parameters?.
In other words, what I have to do if the callback_list
class template is defined with a variadic template?:
template<typename... ARGS>
class callback_list{ ... };
How can I bind a variadic function with any function parameter known at the point of the std::bind()
call, i.e., with an unspecified number of placeholders?