Pass and call a member function (boost::bind / boost::function?)

BaCh picture BaCh · Mar 9, 2011 · Viewed 14.3k times · Source

I have a probably embarassingly simple problem: pass and call a member function in a class. I know I want to use BOOST bind (and or function), but I haven't really grasped the concept to it yet.

The following code compiles and executes with problem. But when I want to change the "f3" function to a non-static class function, then the fun begins:

#include <iostream>
#include <inttypes.h> 
#include <boost/bind.hpp>
#include <boost/function.hpp>

class Test
{
public:
  void f1();
private:
  void f2(void (*callfunc)(uint32_t));
  static void f3(uint32_t x);
};

void Test::f1(){
  f2(f3);
}

void Test::f2(void (*callfunc)(uint32_t)){
  (*callfunc)(42);
}

void Test::f3(uint32_t x){
  std::cout << "x: " << x << std::endl;
}

int main(int argc, char ** argv)
{
  Test ct;
  ct.f1();
  return 0;
}

Now, after changing

static void f3(uint32_t x);

to

void f3(uint32_t x);

the compiler isn't happy and tells me "error: no matching function for call to 'Test::f2()'"

Having read through a number of SO posts regarding boost::bind and boost::function, I think I need to change the definition of f2() and how f1() calls f2() giving f3() as target to call, but apart from that ... about every combination of boost::bind and boost function I tried miserably fails to compile.

How do I need to write this? As a bonus question: are there any simple introductory reads on boost::bind and boost::function? The BOOST docs did not really help me there.

B.

Answer

CashCow picture CashCow · Mar 9, 2011

boost::function is a template class, that takes a function signature. You can also use function0, function1, etc.

boost::function< void(uint32_t) >

defines a "callable" that looks like a function, i.e. it takes a single parameter of type uint32_t and returns void.

The appropriate numbered template is function1< void, uint32_t >. These always indicate the return type first, then the parameters in order.

boost::bind is a very special function that deduces the arguments you pass into it and creates a functor for you.

It will not create a void(uint32_t) for you, it will create something that has the pattern of one.

Therefore change your signature to:

void f2(boost::function<void(uint32_t)>);

Then you can call it like this:

f2( boost::bind( &Test::f3, this, _1 ) );

Note the strange _1 is a "placeholder" telling boost::bind where it needs to put in the parameter, in this case the uint32_t