You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在boost::sml状态机的direct process方法中向事件传递数据?

关于Boost SML中process动作传递状态机依赖的问题解答

问题描述

改写了Boost SML官方文档中process和defer的示例代码,尝试将外部依赖传递给状态机用于事件处理。当前疑问:能否直接在process(e2{/*此处传入my_dependency*/})中从状态机依赖列表获取数据并传递?还是只能采用lambda方式?是否支持内联实现?

附改写后的示例代码:

// $CXX -std=c++14 defer_and_process.cpp
#include <boost/sml.hpp>
#include <cassert>
#include <deque>
#include <queue>

namespace sml = boost::sml;

namespace {
struct e1 {};
struct e2 {int dependency = 0;};
struct e3 {};
struct e4 {};

struct defer_and_process {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(
       *"idle"_s + event<e1> / defer
      , "idle"_s + event<e2> = "s1"_s
      , "s1"_s   + event<e1> / process(e2{/*pass my_dependency here*/}) = "s2"_s // 疑问点
      , "s2"_s   + event<e3> / process(e4{})
      , "s2"_s   + event<e4> = X
    );
  }
};
}  // namespace

int main() {
  int my_dependency = 42;
  using namespace sml;
  sm<defer_and_process, sml::defer_queue<std::deque>, sml::process_queue<std::queue>>
      sm{my_dependency}; 
  assert(sm.is("idle"_s));

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

  assert(!sm.process_event(e2{}));  /// 触发 idle -> s1 以及 s1 -> s2(通过延迟的e1)
  assert(sm.is("s2"_s));

  assert(sm.process_event(e3{}));  /// 触发 s2.process(e4) -> X(通过处理的e4)
  assert(sm.is(sml::X));
}

解答

1. 直接在process(e2{...})中引用状态机依赖不可行

不能直接在process(e2{/*pass my_dependency here*/})里从状态机依赖列表获取数据,原因如下:

  • 转换表make_transition_table是在defer_and_process的operator()中编译期构建的,此时状态机实例还未创建,而my_dependency是运行时传入状态机的,两者作用域、生命周期不匹配。
  • operator()是const成员函数,无法访问状态机实例的依赖数据。

2. 必须使用lambda方式,且支持内联实现

正确的做法是通过lambda动作接收状态机依赖,内联完成事件构造与处理。Boost SML会自动将状态机的依赖注入到lambda参数中,只要参数类型与依赖类型匹配。

修改后的关键代码如下:

struct defer_and_process {
  auto operator()() const noexcept {
    using namespace sml;
    return make_transition_table(
       *"idle"_s + event<e1> / defer
      , "idle"_s + event<e2> = "s1"_s
      // 使用lambda接收依赖,内联构造e2并返回process动作
      , "s1"_s   + event<e1> / [](const int& dep) { return sml::process(e2{dep}); } = "s2"_s
      , "s2"_s   + event<e3> / process(e4{})
      , "s2"_s   + event<e4> = X
    );
  }
};

3. 原理说明

当状态机构造时传入my_dependency,Boost SML会在触发对应转换时,将该依赖作为参数传递给lambda。lambda内可以直接使用这个依赖值构造e2事件,再通过sml::process将事件提交到状态机的处理队列中,实现依赖传递的效果。

内容的提问来源于stack exchange,提问作者DrDreadful

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:13:33