Function pointer to an instance member
I need to map some state to a particular member function of a class, for (a very cut down) example:
class Z {
_a_ptr_to_some_member _p;
void UpdateGuiForStopState(State s) {
// do something with state开发者_StackOverflow
}
Z() {
// setup _p to point to UpdateGuiForStopState
}
void StateComesInHere(State s) {
if(s.id == STOP_ID) { // eventually use lookup
_p(s);
}
}
}
Using just the STL (can't use third party stuff like boost), What is the type of _a_ptr_to_some_member and how do I bind the method UpdateGuiForStopState to it?
Presumably I use the stl mem_xxx stuff but can't work out how.
And yes I can do this a hundred and one other different ways, but I want to work out if this way is possible.
Using STL's bind1st
and mem_fun
:
class Z3 {
typedef std::mem_fun1_t<void,Z3,State> _a_ptr_to_some_member_raw;
typedef std::binder1st<_a_ptr_to_some_member_raw> _a_ptr_to_some_member;
_a_ptr_to_some_member _p;
void UpdateGuiForStopState(State s) {
// do something with state
}
Z3() : _p(std::bind1st(std::mem_fun(&Z3::UpdateGuiForStopState), this))
{
}
void StateComesInHere(State s) {
if(s.id == STOP_ID) { // eventually use lookup
_p(s);
}
}
};
You can do this using just raw pointers to members:
typedef void (Z::*_a_ptr_to_some_member)(State s);
_a_ptr_to_some_member _p;
...
_p = &Z::UpdateGuiForStopState;
...
(this->*_p)(s);
That's a bit old school these days, and the syntax is a bit hairy, but it should work. (Caveat: I haven't tried it.)
The first bit defines the correct type of pointer to a member function and declares a member variable of that type.
The second bit initialises _p to point to the correct function (you can't shorten this, that's the required syntax).
The third bit calls the member function pointed to by _p; to do that you have to supply an instance of Z - in this case the one pointed to by this. I think the extra parenthese are needed; the operator precedence is a bit weird.
TBH I'd probably use bind (from boost, tr1, or C++11) for this; it's very slightly slower, but easier and more flexible.
You should use a std::function
, or, boost::function
if you don't have C++0x/TR1 support. The easiest way to use them would be using boost::bind
or std::bind
, I wouldn't use the Standard's bind1st
and such mess when boost::bind
is much better and easier.
Here is a working example (see http://ideone.com/VEmRZ):
#include <iostream>
typedef enum { s0, s1, s2 } State ;
class Z {
public:
void f0 (State s) { std::cout << "f0" << std::endl ; }
void f1 (State s) { std::cout << "f1" << std::endl ; }
} ;
typedef void (Z::*_a_ptr_to_some_member)(State s);
int main()
{
Z z ;
_a_ptr_to_some_member _p = &Z::f0 ;
(z.*_p)(s0) ;
_p = &Z::f1 ;
(z.*_p)(s2) ;
}
精彩评论