6

I'm trying to use boost::msm library to create a state machine in my code. Does anyone know a way to get a string name (not int id) of a state? I am trying to get this for logging/debugging purpose. For example in no_transition function, I get the state id but I'm trying to get a name so it's easier to read:

template <class Event ,class Fsm>
    void no_transition(Event const& e, Fsm& fsm, int stateId)
    {
        //This is what I'm trying: 
        auto state = fsm.get_state_by_id(stateId); //This returns a boost::msm::front::default_base_state. Anything I can override in there to set a name?
        const char* stateName = state->getStateName(); //I want to do something like this since I can do e.getEventId()

        print("FSM rejected the event %s as there is no transition from current state %s (%d)\n", e.getEventId(), stateName, stateId);
    }

Here's how I defined an event and a state: State:

struct Idle : front::state<> {
 static const char* const getStateName() {
        return "Idle";
    }
};

Event:

struct SampleEvent {
    SampleEvent() {}
    static const char* const getEventId() {
        return "SampleEvent";
    }
};

Any ideas would be great. Thanks!

user1950039
  • 61
  • 1
  • 3

2 Answers2

5

You can achieve the desired effect using the following code:

 #include <boost/msm/back/tools.hpp>
 #include <boost/msm/back/metafunctions.hpp>
 #include <boost/mpl/for_each.hpp>
  .......
  .......
    template <class Event ,class Fsm>
    void no_transition(Event const& e, Fsm& fsm, int stateId){
        typedef typename boost::msm::back::recursive_get_transition_table<FSM>::type recursive_stt;
        typedef typename boost::msm::back::generate_state_set<recursive_stt>::type all_states;
        std::string stateName;
        boost::mpl::for_each<all_states,boost::msm::wrap<boost::mpl::placeholders::_1> >(boost::msm::back::get_state_name<recursive_stt>(stateName, state));
        std::cout << "No transition from state: " << stateName << std::endl;}
Kikosha
  • 343
  • 6
  • 16
  • It does work, but produces a rather ugly string e.g.: `N5boost3msm5front4euml10func_stateIN3rtc5avtp38StarttagENS2_8NoActionES7_NS_6fusion6vectorIJEEENS_3mpl7vector0IN4mpl_2naEEESF_NS1_18default_base_stateEEE` – erikzenker Dec 06 '16 at 09:49
  • 3
    In the end, you could demangle the `stateName` with `boost::core::demangle(stateName.c_str())`. – erikzenker Dec 20 '16 at 08:33
4
  1. Best option: using a visitor.
    Have a look to http://www.boost.org/doc/libs/1_53_0/libs/msm/doc/HTML/examples/SM-2Arg.cpp

  2. Use the last argument (state_id) of no_transition, you could retrieve the name from an array:

    static char const* const state_names[] = { "State1", "State2", ... };
    print(state_names[state_id]);

Pay attention to the fact that a state ID is provided for debugging purpose only. The ID is generated at compiling time and depends on the order of the entries in the transition table

References to MSM documentation:

ropieur
  • 120
  • 1
  • 7
  • Yeah, this is actually exactly what I ended up doing and I did notice that order matters for state ID. Thanks. This is error prone but works! – user1950039 Jul 21 '14 at 23:21