简体   繁体   中英

How to spread/split the implementation of a boost::msm state machine into multiple files?

I want to split the implementation of boost::msm statemachine into multiple files. I am looking for sth like:

1) One header per State

2) One header for the main state-machine (the out-most SM) But I don't know how this file should be written

3) the client code that uses the SM.

What I've come up with follows (which does not compile, giving errors in the form of : "invalid use of incomplete type" & other errors).

The first Sample state:

//State1.h
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

struct State1:msmf::state<> 
{
    // Entry action
    template <class Event,class Fsm>
    void on_entry(Event const&, Fsm&) const {
        std::cout << "State1::on_entry()" << std::endl;
    }
    // Exit action
    template <class Event,class Fsm>
    void on_exit(Event const&, Fsm&) const {
        std::cout << "State1::on_exit()" << std::endl;
    }
};

The 2nd Sample state:

//State2.h
#include <iostream>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
struct State2:msmf::state<> 
{
   // Entry action
   template <class Event,class Fsm>
   void on_entry(Event const&, Fsm&) const {
   std::cout << "State2::on_entry()" << std::endl;
   }
   // Exit action
   template <class Event,class Fsm>
   void on_exit(Event const&, Fsm&) const {
        std::cout << "State2::on_exit()" << std::endl;
   }
};

The Main SM:

//MyFsm.h
#include <iostream>
#include <boost/msm/back/state_machine.hpp>     
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

#include "state1.h"
#include "state2.h"     

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

// ----- Events
struct Event1 {};
struct Event2 {};

struct MyFsm_ : msmf::state_machine_def<MyFsm_>
{    
    struct State1;//??? is this the correct way
    struct State2;//???

   // Set initial state
   typedef State1 initial_state;

   // Transition table
   struct transition_table:mpl::vector<
   ...
   >{};
};
// Pick a back-end
typedef msm::back::state_machine<MyFsm_> MyFsm;

The client Code:

//main.h
#include "myfsm.h"

int main()
{
   MyFsm fsm;
   fsm.start();

   fsm.process_event(Event1());
} 

Any help and hint on how to split a boost:msm into multiple files is appreciated.

You can introduce State1 and State2 to MyFsm using public inheritance as follows:

struct MyFsm_ : msmf::state_machine_def<MyFsm_>
{    
    struct State1_ : State1 {}; // use public inheritance
    struct State2_ : State2 {}; // use public inheritance

   // Set initial state
   typedef State1_ initial_state;

   // Transition table
   struct transition_table:mpl::vector<
         msmf::Row < State1_, Event1, State2_, msmf::none, msmf::none >
   >{};
};

In MyFsm_ , use State1_ and State2_ instead of State1 and State2.

I updated your code, then it works.

Here is running demo: https://wandbox.org/permlink/ZrIVQY38C51fZNFY

You can see whole source code. The tab is corresponding to the header files. The left most one has fixed name prog.cc . Is is usually used to place int main() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM