I have a set of callables which I'd like to associate to instances of a particular class Node. Each instance of Node needs only hold one callable, and may call it from a member function. Suppose A, B, and C are callables, which may have different function signatures:
Node n1,n2,n3;
n1.associate(A);
n2.associate(B, 42);
n3.associate(C, "foo");
//...
n1.mem_fn(); //will call A at some point inside some_other_fn()
n2.mem_fn(); //will call B, passing 42 as argument
//...
n1.associate(C, "bar");
n1.mem_fn(); //now C will replace A, and be called from n1::mem_fn() with arg "bar"
How can I accomplish this? The return type of the callables may be different.
No need to use std::bind
anymore. Lambdas are very simple to use to generate on the fly a callable object which also can store any kind of data as you like.
class Node
{
private:
std::function<void(void)> fn;
public:
template <typename F, typename ... PARMS>
void associate( F f, PARMS ... parms )
{
// Generate a lambda which captures all given parms
// and if executed, the lambda calls f with all
// the captured parms. This on the fly generated
// lambda will be stored in std::function
fn = [f, parms...](){ f( parms...); };
}
void mem_fn()
{
// Here we simply call our lambda which will call
// the stored function with the also stored parms
fn();
}
};
void A() { std::cout << "A" << std::endl; }
void B( int i ) { std::cout << "B " << i << std::endl; }
void C( const std::string& s ) { std::cout << "C " << s << std::endl; }
// I use exact copy of your code as copy here:
int main()
{
Node n1,n2,n3;
n1.associate(A);
n2.associate(B, 42);
n3.associate(C, "foo");
n1.mem_fn(); //will call A at some point inside some_other_fn()
n2.mem_fn(); //will call B, passing 42 as argument
//...
n1.associate(C, "bar"); //now C will replace A, and be called from n1::mem_fn() with arg "bar"
n1.mem_fn();
}