[MSM] Boost.MSM: statemachine to transition on templatized event-type

Hi there, 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. Since there is no "new" and all is static, I cannot use the runtime, to specialize my transitions. So instead, I have to use templates! Unfortunately I'm not a template master, and the compiler is giving me an error. Here's what I'm trying: template <typename EventT> struct Machine_ : public msm::front::state_machine_def<Machine_<EventT> > { // ... struct transition_table : mpl::vector< g_row<StateInitial, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateInitial, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateInitial, EventT, StateFloat, &Machine_<EventT>::guardToFloat>, g_row<StateEven, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateEven, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateEven, EventT, StateFloat, &Machine_<EventT>::guardToFloat>, g_row<StateOdd, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateOdd, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateOdd, EventT, StateFloat, &Machine_<EventT>::guardToFloat>, g_row<StateFloat, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateFloat, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateFloat, EventT, StateFloat, &Machine_<EventT>::guardToFloat> >{}; // ... } 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>, etc. Can somebody help in this regard? Thanks. nicesw123 In case you're interested. Here's the code of the complete example that I'm trying to get working: #include <iostream> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/back/state_machine.hpp> 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; }; #if 0 // not used (just an idea) 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; }; #endif template <typename EventT> struct Machine_ : public msm::front::state_machine_def<Machine_<EventT> > { Machine_(const std::string& stateMachineName = "Machine_") : 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; } // 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} {} }; // guards bool guardToEven(const EventT& num) { const long long x = static_cast<long long>(num.getNum()); return ((x == num.getNum()) // is Integral type && ((x % 2) == 0)); } bool guardToOdd(const EventT& num) { const long long x = static_cast<long long>(num.getNum()); return ((x == num.getNum()) // is Integral type && ((x % 2) != 0)); } bool guardToFloat(const EventT& num) { const long long x = static_cast<long long>(num.getNum()); return (x != num.getNum()); // is Floating type } typedef StateInitial initial_state; struct transition_table : mpl::vector< g_row<StateInitial, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateInitial, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateInitial, EventT, StateFloat, &Machine_<EventT>::guardToFloat>, g_row<StateEven, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateEven, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateEven, EventT, StateFloat, &Machine_<EventT>::guardToFloat>, g_row<StateOdd, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateOdd, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateOdd, EventT, StateFloat, &Machine_<EventT>::guardToFloat>, g_row<StateFloat, EventT, StateEven, &Machine_<EventT>::guardToEven>, g_row<StateFloat, EventT, StateOdd, &Machine_<EventT>::guardToOdd>, g_row<StateFloat, EventT, StateFloat, &Machine_<EventT>::guardToFloat> >{}; private: std::string stateMachineName; }; 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; }

On Fri, May 29, 2015 at 10:06 AM, Gavin Lambert <gavinl@compacsort.com> wrote:
On 29/05/2015 17:08, nice sw123 wrote:
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>,
Use msm::g_row instead.
Ok, I've tried it. Unfortunately the compiler is not eating it. So I checked https://github.com/boostorg/msm/blob/c9569d1fb3ce5eae8396eff955180dfbb29ed22... But the following also does *not* work: msm::front::state_machine_def<EventT>::g_row (?)

On Fri, May 29, 2015 at 12:36 PM, nice sw123 <nicesw123@gmail.com> wrote:
On Fri, May 29, 2015 at 10:06 AM, Gavin Lambert <gavinl@compacsort.com>
wrote:
On 29/05/2015 17:08, nice sw123 wrote:
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>,
Use msm::g_row instead.
Ok, I've tried it. Unfortunately the compiler is not eating it.
So I checked
https://github.com/boostorg/msm/blob/c9569d1fb3ce5eae8396eff955180dfbb29ed22...
But the following also does *not* work: msm::front::state_machine_def<EventT>::g_row
(?)
This also does not work: msm::front::state_machine_def<Machine_<EventT>>::g_row (I'm grasping at straws...)

For users browsing Gmane Unfortunately this topic is not in a single thread, but is displayed... segmented into 2 parts (reason: I did not subscribe on the first post [in which I also CC'd the author of MSM], and had to repost (after subscribing). The author of MSM (Monsieur Henry) has kindly taken the time to write a good response. You can find it here: http://article.gmane.org/gmane.comp.lib.boost.user/84038
participants (2)
-
Gavin Lambert
-
nice sw123