Listing 2
namespace boost{class any;}
template <class DERIVED_FSM,class STATE>
class NO_VTABLE Fsm{
public:
//for stack allocated states
//note that constructors/destructors should not be used in this case,
//instead rely on on_enter/on_exit
typedef typename STATE* (STATE::*Event)(DERIVED_FSM*,const boost::any&);
STATE* dispatch(Event e, const boost::any& arg){
if(curr_state && e){
STATE* next_state=(curr_state->*e)(that(),arg);
if(next_state!=curr_state) transition(next_state);
}
return curr_state;
}
void transition(STATE* next_state){
if(curr_state==next_state) return;
if(curr_state) curr_state->on_exit(that(),next_state);
if(next_state) next_state->on_enter(that(),curr_state);
curr_state=next_state;
}
protected:
Fsm():curr_state(0){}
virtual ~Fsm(){}
private:
STATE* curr_state;
inline DERIVED_FSM* that(){ return static_cast<DERIVED_FSM*>(this);}
};
template<class FSM,class STATE>
class NO_VTABLE IState_base{
protected:
virtual ~IState_base(){}
public:
virtual void on_exit (FSM*,STATE* new_state){}
virtual void on_enter(FSM*,STATE* old_state){}
#if _MSC_VER < 1200
#error derives_from() will not compile in VC++ before version 7./
create this as stand-alone fn then.
#endif
template<class T>
bool derives_from(T*){
const char* derives= 0!=dynamic_cast<T*>(this)?"YES":"NO";
printf("\n%s derives from %s ?-%s",
typeid(*this).name(),typeid(T).name(),derives);
return 0!=dynamic_cast<T*>(this);
}
};