【问题标题】:Boost MSM: using state machine itself as implicit top level stateBoost MSM:使用状态机本身作为隐式顶级状态
【发布时间】:2019-11-20 11:58:07
【问题描述】:

我有一个状态机,其状态为 ABCC 直接处理事件e,而AB 不处理,但我想回退到事件e 的默认处理程序(Samek 称之为“最终挂钩”模式)(这将是在状态 AB 中找不到处理程序时调用)。但是,使用 Boost MSM,我无法在状态机级别实现此处理程序,而必须引入一个额外的容器状态 S,其中包含 ABC

有没有办法直接在状态机级别实现事件处理程序,而不需要这个容器状态?

【问题讨论】:

    标签: c++ statechart boost-msm


    【解决方案1】:

    您可以使用 no_transition 处理程序来做到这一点。

    假设事件 E 定义如下:

    struct E {
        int val = 42;
    };
    

    以下是事件 E 的 no_transition 处理程序示例:

    template <typename Fsm> 
    void no_transition(E const& e, Fsm&, int state) {
        std::cout << "no transition at state " << state << " event e.val" << e.val << std::endl;
    }
    

    但是,由于元编程,Boost.MSM 需要其他类型的 no_transition 处理程序。

    所以你需要为其他事件定义 no_transition 处理程序如下:

    template <typename Fsm, typename Event> 
    void no_transition(Event const&, Fsm& ,int) {
        std::cout << "shouldn't be called but need to define to compile" << std::endl;
    }
    

    你可能认为你可以这样做:

    template <typename Fsm, typename Event> 
    void no_transition(Event const&, Fsm& ,int) {
        std::cout << "no transition at state " << state << " event e.val" << e.val << std::endl;
    }
    

    它不起作用,因为 no_transition 处理程序不仅实例化 E,还实例化其他没有成员变量 val 的事件。

    以下是基于您的问题的完整工作代码示例:

    #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;
    
    // ----- Events
    struct E {
        int val = 42;
    };
    struct AtoB {};
    struct BtoC {};
    
    // ----- State machine
    struct Sm1_:msmf::state_machine_def<Sm1_>
    {
        // States
        struct A:msmf::state<> {
            template <class Event,class Fsm>
            void on_entry(Event const&, Fsm&) {
                std::cout << "A::on_entry()" << std::endl;
            }
        };
        struct B:msmf::state<> {
            template <class Event,class Fsm>
            void on_entry(Event const&, Fsm&) {
                std::cout << "B::on_entry()" << std::endl;
            }
        };
        struct C:msmf::state<> {
            template <class Event,class Fsm>
            void on_entry(Event const&, Fsm&) {
                std::cout << "C::on_entry()" << std::endl;
            }
        };
    
        // Set initial state
        using initial_state = A;
    
        // Transition table
        struct transition_table:mpl::vector<
            //          Start   Event   Next  Action      Guard
            msmf::Row < A,      AtoB,   B,    msmf::none, msmf::none >,
            msmf::Row < B,      BtoC,   C,    msmf::none, msmf::none >,
            msmf::Row < C,      E,      A,    msmf::none, msmf::none >
        > {};
    
        template <typename Fsm> 
        void no_transition(E const& e, Fsm&, int state) {
            std::cout << "no transition at state " << state << " event e.val" << e.val << std::endl;
        }
    
        template <typename Fsm, typename Event> 
        void no_transition(Event const&, Fsm& ,int) {
            std::cout << "shouldn't be called but need to define to compile" << std::endl;
        }
    };
    
    // Pick a back-end
    using Sm1 =  msm::back::state_machine<Sm1_>;
    
    int main() {
        Sm1 sm1;
        sm1.start(); 
        std::cout << "> Send Event E" << std::endl;
        sm1.process_event(E());
        std::cout << "> Send Event AtoB" << std::endl;
        sm1.process_event(AtoB());
        std::cout << "> Send Event E" << std::endl;
        sm1.process_event(E());
        std::cout << "> Send Event BtoC" << std::endl;
        sm1.process_event(BtoC());
        std::cout << "> Send Event E" << std::endl;
        sm1.process_event(E());
    }
    

    现场演示:https://wandbox.org/permlink/NWvuaetwFAm5Nm23

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-06
      • 2013-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-06
      相关资源
      最近更新 更多