boost::msm

昨日の続きです。
実際にステートチャート図を書きながらやってみました。

#include <iostream>

#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>

namespace msm = boost::msm;
namespace mpl = boost::mpl;

// 状態
namespace states{

struct opening : public msm::front::state<>{};
struct menu : public msm::front::state<>{};
struct demo : public msm::front::state<>{};
struct char_select : public msm::front::state<>{};

}        // namespace state


// イベント
namespace event{

struct push_start_button{};
struct opening_end{};
struct menu_time_up{};
struct demo_end{};
struct game_start{};

}        // namespace event


// ゲームの状態を管理
struct game_
     : public msm::front::state_machine_def<game_>{
    
    // 状態遷移のリスト
    struct transition_table : mpl::vector<
        //   Start            Event                     Next
        _row<states::opening, event::push_start_button, states::menu>,
        _row<states::opening, event::opening_end,       states::menu>,
        _row<states::menu,    event::menu_time_up,      states::demo>,
        _row<states::menu,    event::game_start,        states::char_select>,
        _row<states::demo,    event::demo_end,          states::opening>,
        _row<states::demo,    event::push_start_button, states::menu>
    >{};

    // 最初の状態
    typedef states::opening initial_state;

    // イベントが見つからなかった時に呼ばれる
    template <class FSM,class Event>
    void no_transition(Event const& e, FSM&,int state)
    {
        std::cout << "no transition from state " << state
            << " on event " << typeid(e).name() << std::endl;
    }
};

typedef msm::back::state_machine<game_>    game;


int
main(){
    
    game    g;
    
    g.start();
    g.process_event(event::opening_end());       // states::opening -> states::menu
    g.process_event(event::menu_time_up());      // states::menu    -> states::demo
    g.process_event(event::demo_end());          // states::demo    -> states::opening
    g.process_event(event::push_start_button()); // states::opening -> states::menu
    g.process_event(event::game_start());        // states::menu    -> states::char_select
    
    return 0;
}

動きとしては、ステートチャート図の流れを mpl::vector で定義して、
設定したイベントを呼んでやるとその通りに状態が変更されます。
実際にステートチャート図があるとかなり分かりやすい。
今回はやってませんが、状態が変更された時に呼ばれる関数とかも設定出来るみたいです。
ついでに no_transition を定義しておかないと 不正なイベントが呼ばれた場合に、
実行時に吹っ飛んでいくので注意。


まだ骨組みしか出来ていないので、
ここからどうやって拡張していくか悩みどころ。
まぁしかし、大体の流れはつかめたと思います。
コメント欄のアドバイスに感謝。


[boost]
ver 1.44.0
[参照]
http://botamocci.posterous.com/boost-meta-state-machine