...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
We can find for the transition table more uses than what we have seen so far. Let's suppose you need to write a coverage tool. A state machine would be perfect for such a job, if only it could provide some information about its structure. Thanks to the transition table and Boost.MPL, it does.
What is needed for a coverage tool? You need to know how many states are defined in the state machine, and how many events can be fired. This way you can log the fired events and the states visited in the life of a concrete machine and be able to perform some coverage analysis, like “fired 65% of all possible events and visited 80% of the states defined in the state machine”. To achieve this, MSM provides a few useful tools:
generate_state_set<transition table>: returns a mpl::set of all the states defined in the table.
generate_event_set<transition table>: returns a mpl::set of all the events defined in the table.
using mpl::size<>::value you can get the number of elements in the set.
display_type defines an operator() sending typeid(Type).name() to cout.
fill_state_names fills an array of char const* with names of all states (found by typeid)
using mpl::for_each on the result of generate_state_set and generate_event_set passing display_type as argument will display all the states of the state machine.
let's suppose you need to recursively find the states and events defined in the composite states and thus also having a transition table. Calling recursive_get_transition_table<Composite> will return you the transition table of the composite state, recursively adding the transition tables of all sub-state machines and sub-sub...-sub-state machines. Then call generate_state_set or generate_event_set on the result to get the full list of states and events.
An example shows the tools in action.