开发者

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) ;
  }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜