Boost.Statechartを簡単に使うためのabstract_fsm
abstract_fsm – finite state machines in C++
これいいですね。
通常、Boost.Statechartを使うとこれだけのコード量になってしまうのが
#include <boost/statechart/event.hpp> #include <boost/statechart/state_machine.hpp> #include <boost/statechart/simple_state.hpp> #include <boost/statechart/transition.hpp> struct Play : boost::statechart::event<Play> {}; struct Stop : boost::statechart::event<Stop> {}; struct Stopped; struct Playing; struct Machine : boost::statechart::state_machine<Machine, Stopped> { void actStoppedPlayPlaying(const Play& evt) { std::cout << "starting to play" << std::endl; } void actStoppedStopStopped(const Stop& evt) { std::cout << "stopping" << std::endl; } void actPlayingStopStopped(const Stop& evt) { std::cout << "staying in Stopped" << std::endl; } }; struct Stopped : boost::statechart::simple_state<Stopped, Machine> { typedef boost::mpl::list< boost::statechart::transition<Play, Playing, Machine, &Machine::actStoppedPlayPlaying>, boost::statechart::transition<Stop, Stopped, Machine, &Machine::actStoppedStopStopped> reactions; }; struct Playing : boost::statechart::simple_state<Playing, Machine> { typedef boost::mpl::list< boost::statechart::transition<Stop, Stopped, Machine, &Machine::actPlayingStopStopped> > reactions; }; int main(int argc, const char* argv[]) { Machine mach; mach.initiate(); mach.process_event(Stop()); mach.process_event(Play()); mach.process_event(Stop()); }
これらの状態クラスを自動生成するFSM_DEFマクロを使うとこれだけで済みます。
#include <iostream> #include "abstract_fsm.h" FSM_DEF(Machine, // The type of the FSM (Play)(Stop), // the events // The transitions (including the states) ((Stopped, ((Play, Playing, { std::cout << "starting to play" << std::endl; })) ((Stop, Stopped, { std::cout << "stopping" << std::endl; })))) ((Playing, ((Stop, Stopped, { std::cout << "staying in Stopped" << std::endl; })))) ) int main(int argc, const char* argv[]) { Machine mach; mach.initiate(); mach.process_event(Stop()); mach.process_event(Play()); mach.process_event(Stop()); }
現在レビュー中のBoost.MSM(Meta State Machine)にも対応しているようで、
プリプロセスのオプションを変更すれば以下のコードが出力されるそうです。
#include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/state_machine_def.hpp> struct Play {}; struct Stop {}; struct Stopped : boost::msm::front::state<> {}; struct Playing : boost::msm::front::state<> {}; struct Machine_ : boost::msm::front::state_machine_def<Machine_> { typedef Stopped initial_state; void actStoppedPlayPlaying(const Play& evt) { std::cout << "starting to play" << std::endl; } void actStoppedStopStopped(const Stop& evt) { std::cout << "stopping" << std::endl; } void actPlayingStopStopped(const Stop& evt) { std::cout << "staying in Stopped" << std::endl; } typedef boost::mpl::vector< a_row<Stopped, Play, Playing, &Machine_::actStoppedPlayPlaying>, a_row<Stopped, Stop, Stopped, &Machine_::actStoppedStopStopped>, a_row<Playing, Stop, Stopped, &Machine_::actPlayingStopStopped> transition_table; void initiate() {} }; typedef boost::msm::back::state_machine<Machine_> Machine; int main(int argc, const char* argv[]) { Machine mach; mach.initiate(); mach.process_event(Stop()); mach.process_event(Play()); mach.process_event(Stop()); }