StateやStrategyが何種類も出てきたらポインタのサイズが勿体ないので現在のStateをuint8_tで表現したかった。
そしてよく使う環境の都合上C++03縛り。
main.cpp
# include <iostream>
# include <iomanip>
# include <cstdint>
using namespace std;
template <typename T>
class Singleton
{
protected:
Singleton(){}
Singleton(Singleton const&);
~Singleton(){}
Singleton& operator=(Singleton const&);
public:
static T* getInstance()
{
static T i;
return &i;
}
};
class IState
{
public:
IState(){}
virtual ~IState(){}
virtual void action() = 0;
virtual uint8_t getNextState() = 0;
};
template<uint8_t N> class State;
template<>
class State<0> :public IState, public Singleton<State<0> >
{
public:
void action(){ cout << "State0" << endl; }
uint8_t getNextState()
{
return 1;
}
};
template<>
class State<1> :public IState, public Singleton<State<1> >
{
public:
void action(){ cout << "State1" << endl; }
uint8_t getNextState()
{
return 0;
}
};
template<uint8_t N>
static void initialize(IState* s[])
{
s[N - 1] = State<N - 1>::getInstance();
initialize<N-1>(s);
}
template<>
static void initialize<0>(IState* s[])
{
s[0] = State<0>::getInstance();
}
class StateMachine
{
public:
static const int N = 2;
StateMachine():cur_()
{
initialize<N>(states_);
}
void transit()
{
states_[cur_]->action();
cur_ = states_[cur_]->getNextState();
}
private:
IState* states_[N];
uint8_t cur_;
};
int main(int argv, char* argc[])
{
StateMachine state;
state.transit();
state.transit();
state.transit();
return 0;
}
Singletonクラスは以下のページを参考にさせていただきました。
http://d.hatena.ne.jp/setuna-kanata/20090225/1235570379
states_の初期化がもっと綺麗にならないものかなぁ。C++11使いたい。