问题
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.
回答1:
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
回答2:
First, I 'll explain the reason that removing the static
gives you a compilation error:
Take a look at this signature:
void (*callfunc)(uint32_t)
This is a pointer to free function that takes an uint32_t
and returns void
. When f3
is declared inside Test
as
void f3(uint32_t x);
then f3
is a member function of class Test
that takes an uint32_t
and returns void
. Therefore, there is no f3
that matches the type of the argument that f2
is expecting.
As for how boost::function
and boost::bind
can be used to provide a solution:
void Test::f1(){
boost::function<void (uint32_t)> f = boost::bind(&Test::f3, this, _1);
f2(f);
}
Update:
Finally, regarding a tutorial: I found this useful when learning about functors (which is what boost::function
is and boost::bind
returns) in the past. It doesn't mention boost
specifically, but once you understand what exactly is going on in a lower level you will find using boost
a breeze.
来源:https://stackoverflow.com/questions/5245072/pass-and-call-a-member-function-boostbind-boostfunction