[Boost :: ext]SML:通过操作访问SM和依赖项

问题描述

我正在使用SML(https://boost-ext.github.io/sml/)v.1.1.3,需要在操作中访问注入的依赖项和状态机。 根据以下提交,这应该已经起作用:https://github.com/boost-ext/sml/commit/e6d0685993a8a0160dde1610d7f8be4f811c89d0 此提交是此问题的结果: https://github.com/boost-ext/sml/issues/94

在下面的示例中,我尝试在action2中访问依赖项和sm时,出现编译错误: ... sml.hpp:1853:18:注意:无法转换'deps'(类型'boost :: ext :: sml :: v1_1_3 :: aux :: pool ”)以键入“ int&” 1853 |返回对象(事件,sm,deps,subs);

示例:

#include <boost/sml.hpp>
#include <cassert>
#include <iostream>

namespace sml = boost::sml;

namespace {
 
struct e1 {};
struct e2 {};
struct e3 {};

auto action2 = [](const auto& event,auto& sm,int& i,std::string& str) {
    assert(42 == i);
    std::cout << "action2" << std::endl;
    std::cout << "sm.n: " << sm.n << std::endl;
};

struct actions_guards {
    using self = actions_guards;

    int n = 10;

    auto operator()() {
        using namespace sml;

        auto action1 = [](auto e) { std::cout << "action1: " << typeid(e).name() << std::endl; };

        auto guard1 = [](int i) {
            assert(42 == i);
            std::cout << "guard2" << std::endl;
            return false;
        };

        return make_transition_table(
            //  Start           Event             Guard                         Action                        Next
            //+-------------+-------------------+---------------------------+-------------------------------+-------------------------------+
                *"idle"_s   +   event<e1>       [ guard1 ]                  /   action1                     = "s1"_s,"s1"_s      +   event<e2>       [ &self::guard2 ]           /   action2                     = "s2"_s,"s2"_s      +   event<e3>                                                                   = X
        );
    }

    bool guard2(int i) const noexcept {
        assert(42 == i);
        std::cout << "guard3" << std::endl;
        return true;
    }
};

}  // namespace

int main( int argc,char* argv[] )
{
    actions_guards ag{};
    std::string strDep( "127.0.0.1" );
    int intDep = 42;
    sml::sm<actions_guards> sm{ag,intDep,strDep};
    sm.process_event(e1{});
    sm.process_event(e2{});
    sm.process_event(e3{});

    assert(sm.is(sml::X));

    return 0;
}

错误: ... sml.hpp:1340:10:从'bool boost :: ext :: sml :: v1_1_3 :: back :: sm_impl :: process_event(const TEvent&,TDeps&,TSubs&)中需要[with TEvent = {anonymous} ::: e2; TDeps = boost :: ext :: sml :: v1_1_3 :: aux :: pool ; TSubs = boost :: ext :: sml :: v1_1_3 :: aux :: poolboost :: ext :: sml :: v1_1_3 :: back :: sm_impl >; TSM = boost :: ext :: sml :: v1_1_3 :: back :: sm_policy ]” /usr/local/oecore-x86_64_tux_dunfell/sysroots/armv5te-angstrom-linux-gnueabi/usr/include/boost/sml.hpp:1660:81:从'bool boost :: ext :: sml :: v1_1_3 :: back :: sm :: process_event(const TEvent&)[with TEvent = {anonymous} :: e2;类型名称boost :: ext :: sml :: v1_1_3 :: aux :: enable_if :: value,int> :: type = 0; TSM = boost :: ext :: sml :: v1_1_3 :: back :: sm_policy ]” main.cpp:86:23:从这里需要 /usr/local/oecore-x86_64_tux_dunfell/sysroots/armv5te-angstrom-linux-gnueabi/usr/include/boost/sml.hpp:1853:18:错误:与'(boost :: ext :: sml:的调用不匹配:v1_1_3 :: aux :: zero_wrapper ,void>)(const {anonymous} :: e2&,boost :: ext :: sml :: v1_1_3 :: back :: sm_implboost :: ext :: sml :: v1_1_3 :: back :: sm_policy &,boost :: ext :: sml :: v1_1_3 :: aux :: pool &,boost :: ext :: sml :: v1_1_3 :: aux :: poolboost :: ext :: sml :: v1_1_3 :: back :: sm_impl >&)' 1853年|返回对象(事件,sm,deps,subs); | ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~ main.cpp:37:16:注意:候选人:'template {anonymous} :: ' 37 | auto action2 = [](const auto&event,auto&sm,int&i,std :: string&str){ | ^ main.cpp:37:16:注意:模板参数推导/替换失败: 在main.cpp:20包含的文件中: /usr/local/oecore-x86_64_tux_dunfell/sysroots/armv5te-angstrom-linux-gnueabi/usr/include/boost/sml.hpp:1853:18:注意:无法转换'deps'(类型'boost :: ext :: sml :: v1_1_3 :: aux :: pool ')以输入'int&' 1853年|返回对象(事件,sm,deps,subs); | ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~

解决方法

#399期末,SML作者的答案:

此功能的实现已更改,以避免递归调用并符合UML-2.5

示例

s1 + event<e1> / [](sml::back::process<e2,e3> processEvent) -> void {
            processEvent(e2{});
            processEvent(e3{});
          }

定义sm时必须指定process_queue

sml::sm<c,sml::process_queue<std::queue>> sm{};

Full example

这是我实际问题的改编示例:

#include <iostream>
#include <cassert>
#include <queue>
#include <boost/sml.hpp>

namespace sml = boost::sml;

struct e1 {};
struct e2 {};
struct e3 {};

struct my_dep {
    int val = 0;
};

auto action = [](sml::back::process<e2,e3> processEvent,my_dep& dep) {
    if (dep.val == 0) {
        processEvent(e2{});
        ++dep.val;
    }
    else
        processEvent(e3{});
};

struct table {
    auto operator()() const noexcept {
        using namespace sml;
        return make_transition_table(
            *"s1"_s + event<e1> / action = "s3"_s,"s1"_s + event<e2> = "s2"_s,"s3"_s + event<e2> = "s4"_s,"s3"_s + event<e3> = "s5"_s,"s4"_s + event<e1> = "s1"_s
        );
    }
};

int main() {
    using namespace sml;
    my_dep md;
    sm<table,sml::process_queue<std::queue>> sm{md};

    sm.process_event(e1{});
    assert(sm.is("s4"_s));

    sm.process_event(e1{});
    assert(sm.is("s1"_s));

    sm.process_event(e1{});
    assert(sm.is("s5"_s));
}