Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to typedef a pointer to method which returns a pointer the method?

Basically I have the following class:

class StateMachine {
...
StateMethod stateA();
StateMethod stateB();
...
};

The methods stateA() and stateB() should be able return pointers to stateA() and stateB(). How to typedef the StateMethod?

like image 318
grigy Avatar asked Oct 02 '08 05:10

grigy


2 Answers

GotW #57 says to use a proxy class with an implicit conversion for this very purpose.

struct StateMethod;
typedef StateMethod (StateMachine:: *FuncPtr)(); 
struct StateMethod
{
  StateMethod( FuncPtr pp ) : p( pp ) { }
  operator FuncPtr() { return p; }
  FuncPtr p;
};

class StateMachine {
  StateMethod stateA();
  StateMethod stateB();
};

int main()
{
  StateMachine *fsm = new StateMachine();
  FuncPtr a = fsm->stateA();  // natural usage syntax
  return 0;
}    

StateMethod StateMachine::stateA
{
  return stateA; // natural return syntax
}

StateMethod StateMachine::stateB
{
  return stateB;
}

This solution has three main strengths:

  1. It solves the problem as required. Better still, it's type-safe and portable.

  2. Its machinery is transparent: You get natural syntax for the caller/user, and natural syntax for the function's own "return stateA;" statement.

  3. It probably has zero overhead: On modern compilers, the proxy class, with its storage and functions, should inline and optimize away to nothing.

like image 55
Jacob Krall Avatar answered Nov 17 '22 01:11

Jacob Krall


Using just typedef:

class StateMachine {  

 public:  

  class StateMethod;     
  typedef StateMethod (StateMachine::*statemethod)();   

  class StateMethod {  

    statemethod   method; 
    StateMachine& obj; 

   public:  

    StateMethod(statemethod method_, StateMachine *obj_)  
      : method(method_), obj(*obj_) {} 

    StateMethod operator()() { return (obj.*(method))(); }  
  };  

  StateMethod stateA()  { return StateMethod(&StateMachine::stateA, this); }  

  StateMethod stateB()  { return StateMethod(&StateMachine::stateB, this); }  

};    
like image 45
njsf Avatar answered Nov 17 '22 00:11

njsf