Search code examples
c++boostboost-msm

How to visit all states in (boost meta) state machine?


Is there a way to visit all states (not only active ones) in boost msm? E.g. all UI controls placed in states should be resized on a resize event regardless of their state is active or not.

Update: Let me clarify a bit, I need some kind of iterator through all objects-states created by my state machine.

Update #2: Below is an example. I need to call the resize method of all states.

struct EventOne {};
struct EventTwo {};

struct StateOne : public state<> {
    void resize() { }
};

struct StateTwo : public state<> {
    void resize() { }
};

struct MyFsm : public state_machine_def<MyFsm> {
    typedef int no_exception_thrown;
    typedef StateOne initial_state;

    struct transition_table : boost::mpl::vector<
        //      Start,          Event,          Next,           Action,         Guard
        Row<    StateOne,       EventOne,       StateTwo,       none,           none            >,
        Row<    StateTwo,       EventTwo,       StateOne,       none,           none            >
    > {
    };
};

typedef boost::msm::back::state_machine<MyFsm> Fsm;

Solution

  • You have several ways. One would be to use a base class for states, but well, it'd be a base class, so here is the MPL way:

    template <class stt>
    struct Visit
    {
        Visit(Fsm* fsm): fsm_(fsm){}
        template <class StateType>
        void operator()(boost::msm::wrap<StateType> const&)
        {
            StateType& s = fsm_->template get_state<StateType&>();
            s.resize();
        }
        Fsm* fsm_;
    };
    
    Fsm f;
    typedef Fsm::stt Stt;
    // a set of all state types
    typedef boost::msm::back::generate_state_set<Stt>::type all_states; //states
    // visit them all using MPL
    boost::mpl::for_each<all_states,boost::msm::wrap<boost::mpl::placeholders::_1> > (Visit<Stt>(&f));
    

    It's an interesting question, I'll add it to the doc.

    Cheers, Christophe

    PS: this one is a bit too advanced for SO. It'd be faster on the boost list as I'm only an occasional SO visitor.