【问题标题】:How to spread/split the implementation of a boost::msm state machine into multiple files?如何将 boost::msm 状态机的实现传播/拆分为多个文件?
【发布时间】:2018-11-08 05:57:39
【问题描述】:

我想将 boost::msm 状态机的实现拆分成多个文件。我正在寻找类似的东西:

1) 每个州一个标题

2) 主状态机的一个标头(最外面的 SM) 但是我不知道这个文件应该怎么写

3) 使用 SM 的客户端代码。

我想出的内容如下(无法编译,以以下形式给出错误:“不完整类型的无效使用”和其他错误)。

第一个 Sample 状态:

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

第二个样本状态:

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

主要的 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;

客户端代码:

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

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

   fsm.process_event(Event1());
} 

感谢任何有关如何将 boost:msm 拆分为多个文件的帮助和提示。

【问题讨论】:

    标签: c++ boost template-meta-programming state-machine boost-msm


    【解决方案1】:

    您可以使用公共继承将 State1 和 State2 引入 MyFsm,如下所示:

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

    MyFsm_ 中,使用 State1_ 和 State2_ 而不是 State1 和 State2。

    我更新了你的代码,然后它就可以工作了。

    这是正在运行的演示: https://wandbox.org/permlink/ZrIVQY38C51fZNFY

    您可以查看完整的源代码。该选项卡对应于头文件。最左边的有固定名称prog.cc。通常用于放置int main()

    【讨论】:

    • 当在另一个头文件中定义时,如何从状态中访问我的状态机的数据;当状态直接在SM的主体中实现时,我没有问题。我应该使用主 FSM 的前向减速来访问它还是...? //myfsm.h struct MyFsm_ : msmf::state_machine_def&lt;MyFsm_&gt; {.... MyData smData; }; //state1.h struct State1 : msmf::state&lt;&gt; { template&lt;class Event, class Fsm&gt; void on_entry(Event const&amp;, Fsm&amp; fsm) { MyFsm_&amp; sm = static_cast&lt;MyFsm_&amp;&gt;(fsm); sm.smData.print(); } };
    • 哦,就这么简单;我们可以使用传递给状态的引用(即 Fsm 和 sm)直接访问 SM 中的数据(无需强制转换!)。但是,在某些示例中,以下断言的意义何在:BOOST_STATIC_ASSERT((boost::is_convertible&lt;Fsm, OuterSm_&gt;::value)); 再次感谢。
    • 我猜这个例子有子机状态。在这种情况下,msm 传递了正确的状态机(父或子)。但用户有时会感到困惑。这样静态断言有助于在编译时发现错误。
    • 一如既往的感谢;你在redboltz.wikidot.com/boost-msm-guide 的教程很棒。
    猜你喜欢
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    相关资源
    最近更新 更多