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?
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?
My philosophy is don't use raw member function pointers. I don't even really know how to do what you want using raw pointer typedef's the syntax is so horrible. I like using boost::function.
This is almost certainly wrong:
class X
{
public:
typedef const boost::function0<Method> Method;
// some kind of mutually recursive state machine
Method stateA()
{ return boost::bind(&X::stateB, this); }
Method stateB()
{ return boost::bind(&X::stateA, this); }
};
This problem is definitely a lot harder than first meets the eye
EDIT: njsf proved me wrong here. You might find static casting simpler to maintain, however, so I will leave the rest here.
There is no 'correct' static type since the full type is recursive:
typedef StateMethod (StateMachine::*StateMethod)();
Your best bet is to use typedef void (StateMachine::*StateMethod)();
then do the ugly state = (StateMethod)(this->*state)();
PS: boost::function
requires an explicit return type, at least from my reading of the docs: boost::function0<ReturnType>
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:
It solves the problem as required. Better still, it's type-safe and portable.
Its machinery is transparent: You get natural syntax for the caller/user, and natural syntax for the function's own "return stateA;" statement.
It probably has zero overhead: On modern compilers, the proxy class, with its storage and functions, should inline and optimize away to nothing.
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); }
};
I can never remember the horrible C++ function declspec, so whenever I have to find out the syntax that describes a member function, for example, I just induce an intentional compiler error which usually displays the correct syntax for me.
So given:
class StateMachine {
bool stateA(int someArg);
};
What's the syntax for stateA's typedef? No idea.. so let's try to assign to it something unrelated and see what the compiler says:
char c = StateMachine::stateA
Compiler says:
error: a value of type "bool (StateMachine::*)(int)" cannot be used to initialize
an entity of type "char"
There it is: "bool (StateMachine::*)(int)" is our typedef.