Boost logo

Boost Users :

Subject: [Boost-users] [MSM] Boost.MSM: statemachine to transition on templatized event-type
From: nice sw123 (nicesw123_at_[hidden])
Date: 2015-05-29 01:08:30


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;
}



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net