[Boost::ext].SML:在动作中访问 SM 和依赖项
[Boost::ext].SML: Access SM and dependencies in an action
我正在使用 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 | return 对象(事件、sm、部门、潜艇);
示例:
#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<{anonymous}::actions_guards>]’
/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; typename boost::ext::sml::v1_1_3::aux::enable_if::value, int>::type = 0; TSM = boost::ext::sml::v1_1_3::back::sm_policy<{anonymous}::actions_guards>]'
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<{anonymous}: :, void>) (const {匿名}::e2&, boost::ext::sml::v1_1_3::back::sm_implboost::ext::sml::v1_1_3::back::sm_policy<{匿名}::actions_guards>&, 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 年 | return 对象(事件、sm、部门、潜艇);
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
main.cpp:37:16: 注意:候选:'template {anonymous}::'
37 | auto action2 = [](const auto& event, auto& sm, int& i, std::string& str) {
| ^
main.cpp:37:16: 注意:模板参数 deduction/substitution 失败:
在 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 年 | return 对象(事件、sm、部门、潜艇);
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
期末SML作者的回答#399:
此功能的实现已更改以避免递归调用并符合 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{};
这里是我实际问题的改编示例:
#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));
}
我正在使用 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
示例:
#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
期末SML作者的回答#399:
此功能的实现已更改以避免递归调用并符合 UML-2.5
例子
s1 + event<e1> / [](sml::back::process<e2, e3> processEvent) -> void {
processEvent(e2{});
processEvent(e3{});
}
定义sm
时必须指定process_queuesml::sm<c, sml::process_queue<std::queue>> sm{};
这里是我实际问题的改编示例:
#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));
}