C++ msm用法:如何设置目标状态的属性

C++ msm用法:如何设置目标状态的属性,c++,boost,C++,Boost,我的fsm中的状态具有不同的属性。我定义了一个事件,它将调用到目标状态的转换。我想按事件数据设置目标的属性。我的选择是: 1.在操作或保护中设置属性:但仍处于源状态。如果当时设置了目标状态属性,则填充不好 2.在目标条目中设置属性:但是属性的值在收到事件时已在guard中计算,因此我应该重新计算:( 任何人都可以给我更多的想法。谢谢!我不确定您的情况,但我认为您有两个不同的问题。一个是设置目标状态属性的最佳位置。另一个是如何避免重新计算 让我们考虑前一个问题。正如你提到的,有两个候选者。它们是一

我的fsm中的状态具有不同的属性。我定义了一个事件,它将调用到目标状态的转换。我想按事件数据设置目标的属性。我的选择是: 1.在操作或保护中设置属性:但仍处于源状态。如果当时设置了目标状态属性,则填充不好 2.在目标条目中设置属性:但是属性的值在收到事件时已在guard中计算,因此我应该重新计算:(


任何人都可以给我更多的想法。谢谢!

我不确定您的情况,但我认为您有两个不同的问题。一个是设置目标状态属性的最佳位置。另一个是如何避免重新计算

让我们考虑前一个问题。正如你提到的,有两个候选者。它们是一个过渡动作和一个目标状态的进入动作。我认为两者都可以。如果使用目标状态的入口动作,则需要关心事件类型。如果编写如下的处理程序,所有事件都会被处理程序捕获。

    template <class Event, class Fsm>
    void on_entry(Event const& e, Fsm&) {
        std::cout << "State2::on_entry()" << std::endl;
        std::cout << "You can also set the property here." << std::endl;
        property = e.data;
    }
因为Boost.MSM将事件参数作为常量引用传递

下面是一段代码,描述如何在不重新计算的情况下设置目标状态属性:

#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 <boost/static_assert.hpp>

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

// StateMachine [Sm]
//
// (initial)
//    |
//    V
// State1 --Event1[Guard1]/Action1--> State2
//

// ----- Events
struct Event1 {
    mutable int data; // mutable is required because Event is passed as const&.
};

struct Sm_:msmf::state_machine_def<Sm_>
{
    // States
    struct State1:msmf::state<>
    {
        template <class Event,class Fsm>
        void on_entry(Event const&, Fsm&) const {
            std::cout << "State1::on_entry()" << std::endl;
        }
        template <class Event,class Fsm>
        void on_exit(Event const&, Fsm&) const {
            std::cout << "State1::on_exit()" << std::endl;
        }
    };
    struct State2:msmf::state<>
    {
        template <class Event,class Fsm>
        void on_entry(Event const& e, Fsm&) {
            std::cout << "State2::on_entry()" << std::endl;
            std::cout << "You can also set the property here." << std::endl;
            property = e.data;
        }
        template <class Event,class Fsm>
        void on_exit(Event const&, Fsm&) const {
            std::cout << "State2::on_exit()" << std::endl;
        }
        int property;
    };
    // Set initial state
    typedef State1 initial_state;

    // Guards
    struct Guard1 {
        template <class Event, class Fsm, class Source, class Target>
        bool operator()(Event const& e, Fsm&, Source&, Target&) const {
            e.data *= 2; // calc
            std::cout << "In Guard1, e.data *= 2. e.data=" << e.data << std::endl;
            return true;
        }
    };

    // Actions
    struct Action1 {
        template <class Event, class Fsm, class Source, class Target>
        void operator()(Event const& e, Fsm&, Source&, Target& t) const {
            std::cout << "In Action1, set target state property based on event data that is calculated in Guard1." << std::endl;
            t.property = e.data;
        }
    };

    // Transition table
    struct transition_table:mpl::vector<
        //          Start   Event   Next    Action      Guard
        msmf::Row < State1, Event1, State2, Action1,    Guard1 >
    > {};
};

// Pick a back-end
typedef msm::back::state_machine<Sm_> Sm;

void test()
{
    Sm sm;
    sm.start();

    std::cout << "> Send Event1()" << std::endl;
    Event1 e1;
    e1.data = 12;
    sm.process_event(e1);
}

int main()
{
    test();
}
#包括
#包括
#包括
#包括
#包括
名称空间msm=boost::msm;
名称空间msmf=boost::msm::front;
名称空间mpl=boost::mpl;
//状态机[Sm]
//
//(首字母)
//    |
//五
//状态1—事件1[Guard1]/Action1-->状态2
//
//----事件
结构事件1{
mutable int data;//需要mutable,因为事件作为常量传递。
};
结构Sm:msmf::状态机定义
{
//州
结构State1:msmf::state
{
模板
输入时无效(事件常量,Fsm&)常量{

std::cout我不确定您的情况,但我认为您有两个不同的问题。一个是设置目标状态属性的最佳位置。另一个是如何避免重新计算

让我们考虑前一个问题。正如你提到的,有两个候选者。它们是一个过渡动作和一个目标状态的进入动作。我认为两者都可以。如果使用目标状态的入口动作,则需要关心事件类型。如果编写如下的处理程序,所有事件都会被处理程序捕获。

    template <class Event, class Fsm>
    void on_entry(Event const& e, Fsm&) {
        std::cout << "State2::on_entry()" << std::endl;
        std::cout << "You can also set the property here." << std::endl;
        property = e.data;
    }
因为Boost.MSM将事件参数作为常量引用传递

下面是一段代码,描述如何在不重新计算的情况下设置目标状态属性:

#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 <boost/static_assert.hpp>

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

// StateMachine [Sm]
//
// (initial)
//    |
//    V
// State1 --Event1[Guard1]/Action1--> State2
//

// ----- Events
struct Event1 {
    mutable int data; // mutable is required because Event is passed as const&.
};

struct Sm_:msmf::state_machine_def<Sm_>
{
    // States
    struct State1:msmf::state<>
    {
        template <class Event,class Fsm>
        void on_entry(Event const&, Fsm&) const {
            std::cout << "State1::on_entry()" << std::endl;
        }
        template <class Event,class Fsm>
        void on_exit(Event const&, Fsm&) const {
            std::cout << "State1::on_exit()" << std::endl;
        }
    };
    struct State2:msmf::state<>
    {
        template <class Event,class Fsm>
        void on_entry(Event const& e, Fsm&) {
            std::cout << "State2::on_entry()" << std::endl;
            std::cout << "You can also set the property here." << std::endl;
            property = e.data;
        }
        template <class Event,class Fsm>
        void on_exit(Event const&, Fsm&) const {
            std::cout << "State2::on_exit()" << std::endl;
        }
        int property;
    };
    // Set initial state
    typedef State1 initial_state;

    // Guards
    struct Guard1 {
        template <class Event, class Fsm, class Source, class Target>
        bool operator()(Event const& e, Fsm&, Source&, Target&) const {
            e.data *= 2; // calc
            std::cout << "In Guard1, e.data *= 2. e.data=" << e.data << std::endl;
            return true;
        }
    };

    // Actions
    struct Action1 {
        template <class Event, class Fsm, class Source, class Target>
        void operator()(Event const& e, Fsm&, Source&, Target& t) const {
            std::cout << "In Action1, set target state property based on event data that is calculated in Guard1." << std::endl;
            t.property = e.data;
        }
    };

    // Transition table
    struct transition_table:mpl::vector<
        //          Start   Event   Next    Action      Guard
        msmf::Row < State1, Event1, State2, Action1,    Guard1 >
    > {};
};

// Pick a back-end
typedef msm::back::state_machine<Sm_> Sm;

void test()
{
    Sm sm;
    sm.start();

    std::cout << "> Send Event1()" << std::endl;
    Event1 e1;
    e1.data = 12;
    sm.process_event(e1);
}

int main()
{
    test();
}
#包括
#包括
#包括
#包括
#包括
名称空间msm=boost::msm;
名称空间msmf=boost::msm::front;
名称空间mpl=boost::mpl;
//状态机[Sm]
//
//(首字母)
//    |
//五
//状态1—事件1[Guard1]/Action1-->状态2
//
//----事件
结构事件1{
mutable int data;//需要mutable,因为事件作为常量传递。
};
结构Sm:msmf::状态机定义
{
//州
结构State1:msmf::state
{
模板
输入时无效(事件常量,Fsm&)常量{

你的代码解决了我的问题。非常感谢。你的代码解决了我的问题。非常感谢。