
On Fri, May 29, 2015 at 4:00 PM, Christophe Henry < christophe.j.henry@gmail.com> wrote:
Hi,
having tested Boost.MSM, I'm pretty happy with it.
:)
It's interesting, in that it seems to handle all states in a static
table.
No "new" operator etc.
It's much faster without dynamic allocation.
<snip>
g_row<StateInitial, EventT, StateEven, &Machine_<EventT>::guardToEven>,
Unfortunately gcc gives this error: d.cpp:119:5: error: ‘g_row’ was not declared in this scope g_row<StateInitial, EventT, StateEven, &Machine_<EventT>::guardToEven>,
Short answer. Try:
typename Machine_<EventT>::template g_row<StateFloat, EventT, StateFloat, &Machine_<EventT>::guardToFloat>
Thanks so much for taking the time to help out! This works perfectly!!!
Long answer: g_row is a type of state_machine_def and as your fsm is a template, it becomes a dependent type (=> typename) and a template one even (=> template).
C++ is sometimes really annoying :(
Longer answer. Give up this front-end, it's deprecated anyway. A better solution will be:
#include <boost/msm/front/functor_row.hpp> using namespace boost::msm::front;
struct GuardToOdd { template <class EVT,class FSM,class SourceState,class TargetState> bool operator()(EVT const& num,FSM& ,SourceState& ,TargetState& ) { const long long x = static_cast<long long>(num.getNum()); return ((x == num.getNum()) // is Integral type && ((x % 2) != 0)); } };
Row< StateFloat, EventT, StateOdd, none, GuardToOdd>
I've tried it! Nice, thanks.
HTH, Christophe
I have a question about optimization regarding guard conditions. How can one optimize the states and guard-checking?? This is one way: /// see full working code example at the bottom of this post struct transition_table : mpl::vector< Row<StateInitial, EventT, StateEven, none, none>, Row<StateInitial, EventT, StateOdd, none, GuardToOdd>, Row<StateInitial, EventT, StateFloat, none, GuardToFloat>, Row<StateEven, EventT, StateEven, none, none>, Row<StateEven, EventT, StateOdd, none, GuardToOdd>, Row<StateEven, EventT, StateFloat, none, GuardToFloat>, Row<StateOdd, EventT, StateEven, none, none>, Row<StateOdd, EventT, StateOdd, none, GuardToOdd>, Row<StateOdd, EventT, StateFloat, none, GuardToFloat>, Row<StateFloat, EventT, StateEven, none, none>, Row<StateFloat, EventT, StateOdd, none, GuardToOdd>, Row<StateFloat, EventT, StateFloat, none, GuardToFloat> >{}; which relies on the guard-checking from the bottom to the top (first guard returning true wins). The guards can then be: struct GuardToOdd { template <class EVT, class FSM, class SourceState, class TargetState> bool operator()(EVT const& num, FSM&, SourceState&, TargetState&) { const long long x = static_cast<long long>(num.getNum()); /* do not have to check if number is float or integral here. Reason: GuardToFloat is guaranteed to be false if we are here, because it is lower in transition_table !!!!!! */ return ((x % 2) != 0); } }; struct GuardToFloat { template <class EVT, class FSM, class SourceState, class TargetState> bool operator()(EVT const& num, FSM&, SourceState&, TargetState&) { const long long x = static_cast<long long>(num.getNum()); return (x != num.getNum()); // is Floating type } }; But the transition table is still huge. Is it possible to use MSM to create a parentstate "StateEval" with substates "StateEven", "StateOdd", "StateFloat" ?, the idea being to make transition_table as short as possible. Something like this maby (but it does not work): struct transition_table : mpl::vector< Row<StateEval, EventT, StateEval::StateEven, none, none>, Row<StateEval, EventT, StateEval::StateOdd, none, GuardToOdd>, Row<StateEval, EventT, StateEval::StateFloat, none, GuardToFloat> >{}; Basically: is it possible to create a parentstate, that listens to events (even when an inner substate is already active)? Thanks. nicesw123 Full code-example (using large transition_table): #include <iostream> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/functor_row.hpp> using namespace boost::msm::front; namespace msm = boost::msm; namespace mpl = boost::mpl; // events struct EventNumber1 { // int number! EventNumber1(int num_) : num{num_} {} int getNum() const { return num; } private: int num; }; struct EventNumber2 { // double number! EventNumber2(double num_) : num{num_} {} double getNum() const { return num; } private: double num; }; typedef EventNumber2 MyEvent; // using doubles // StateBase -- a base (parent) state struct StateBase : public msm::front::state<> { StateBase(const std::string& stateName = "") : stateName{stateName} {} template <typename Event, typename FSM> void on_entry(const Event&, FSM&) { std::cout << "Entering " << stateName << std::endl; } template <typename Event, typename FSM> void on_exit(const Event&, FSM&) { std::cout << "Leaving " << stateName << std::endl; } private: std::string stateName; }; template <typename T> struct StateMachineFront_Base : public msm::front::state_machine_def<StateMachineFront_Base<T>> { StateMachineFront_Base(const std::string& stateMachineName = "") : stateMachineName{stateMachineName} {} template <typename Event, typename FSM> void on_entry(const Event&, FSM&) { std::cout << "Entering " << stateMachineName << std::endl; } template <typename Event, typename FSM> void on_exit(const Event&, FSM&) { std::cout << "Leaving " << stateMachineName << std::endl; } private: std::string stateMachineName; }; //guards struct GuardToOdd { template <class EVT, class FSM, class SourceState, class TargetState> bool operator()(EVT const& num, FSM&, SourceState&, TargetState&) { const long long x = static_cast<long long>(num.getNum()); return ((x % 2) != 0); } }; struct GuardToFloat { template <class EVT, class FSM, class SourceState, class TargetState> bool operator()(EVT const& num, FSM&, SourceState&, TargetState&) { const long long x = static_cast<long long>(num.getNum()); return (x != num.getNum()); // is Floating type } }; template <typename EventT> struct Machine_ : public StateMachineFront_Base<Machine_<EventT> > { Machine_(const std::string& stateMachineName = "Machine_") : StateMachineFront_Base<Machine_<EventT> >{stateMachineName} {} // states struct StateInitial : public StateBase { StateInitial(const std::string name = "StateInitial") : StateBase{name} {} }; struct StateEven : public StateBase { StateEven(const std::string name = "StateEven") : StateBase{name} {} }; struct StateOdd : public StateBase { StateOdd(const std::string name = "StateOdd") : StateBase{name} {} }; struct StateFloat : public StateBase { StateFloat(const std::string name = "StateFloat") : StateBase{name} {} }; typedef StateInitial initial_state; struct transition_table : mpl::vector< Row<StateInitial, EventT, StateEven, none, none>, Row<StateInitial, EventT, StateOdd, none, GuardToOdd>, Row<StateInitial, EventT, StateFloat, none, GuardToFloat>, Row<StateEven, EventT, StateEven, none, none>, Row<StateEven, EventT, StateOdd, none, GuardToOdd>, Row<StateEven, EventT, StateFloat, none, GuardToFloat>, Row<StateOdd, EventT, StateEven, none, none>, Row<StateOdd, EventT, StateOdd, none, GuardToOdd>, Row<StateOdd, EventT, StateFloat, none, GuardToFloat>, Row<StateFloat, EventT, StateEven, none, none>, Row<StateFloat, EventT, StateOdd, none, GuardToOdd>, Row<StateFloat, EventT, StateFloat, none, GuardToFloat> >{}; }; typedef msm::back::state_machine<Machine_<MyEvent>> Machine; template <typename T> void postEvents(Machine& machine) { for (T i; std::cin >> i; ) { machine.process_event(MyEvent{i}); } } int main() { Machine machine; machine.start(); postEvents<double>(machine); machine.stop(); return 0; }