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

Boost SML:如何基于当前事件处理结果决定下一状态?

Boost SML中基于事件处理结果决定下一状态的标准做法

针对你遇到的问题,Boost SML里有两种核心方案可以解决,既避免重复计算,又能在处理完当前事件后立即判断状态转移:

1. 用上下文存储计算结果,结合守卫+内部事件实现即时判断

核心思路

  • 把累加值、接收上限这类状态数据存在状态机的**上下文(context)**中,动作处理事件时只计算一次并更新上下文,后续逻辑直接读取上下文的值,彻底避免重复计算。
  • 处理完receive事件的累加动作后,发送一个内部事件(比如check_termination),在当前状态下立即处理这个内部事件,根据上下文的累加值决定是回到等待接收的状态,还是进入终止状态。

代码示例

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

// 定义事件
struct receive { int data; };
struct check_termination {}; // 内部判断事件

// 上下文:存储状态数据
struct receiver_ctx {
    int total = 0;
    const int upper_limit = 100; // 设定的接收上限
};

namespace sml = boost::sml;

// 守卫:直接读取上下文的值,无需重复计算
auto g_not_done = [](const receiver_ctx& ctx) {
    return ctx.total < ctx.upper_limit;
};

// 动作:处理receive事件,累加数据到上下文
auto a_receive = [](const receive& evt, receiver_ctx& ctx) {
    ctx.total += evt.data;
    std::cout << "当前累加值:" << ctx.total << std::endl;
};

// 状态转移表
struct receiver_sm {
    auto operator()() const {
        using namespace sml;
        return make_transition_table(
            // idle状态收到receive事件,进入reading,执行累加后发送内部判断事件
            *state<class idle> + event<receive> / (a_receive, process_event(check_termination{})) = state<class reading>,
            
            // reading状态处理内部事件,根据守卫判断转移方向
            state<class reading> + event<check_termination> [g_not_done] = state<class idle>,
            state<class reading> + event<check_termination> = state<class terminated>
        );
    }
};

int main() {
    receiver_ctx ctx;
    sml::sm<receiver_sm> sm{ctx};

    // 模拟接收事件
    sm.process_event(receive{30});
    sm.process_event(receive{40});
    sm.process_event(receive{40}); // 累加后达到110,超过上限

    return 0;
}

2. 直接在动作中返回转移目标(C++17及以上)

Boost SML支持在动作中返回sml::result类型,直接指定下一状态,这种方式更简洁,无需定义额外的内部事件:

代码示例

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

struct receive { int data; };

struct receiver_ctx {
    int total = 0;
    const int upper_limit = 100;
};

namespace sml = boost::sml;

// 动作:处理累加,并根据结果返回下一状态
auto a_handle_receive = [](const receive& evt, receiver_ctx& ctx) -> sml::result {
    ctx.total += evt.data;
    std::cout << "当前累加值:" << ctx.total << std::endl;

    if (ctx.total < ctx.upper_limit) {
        return sml::transition<class idle>; // 返回转移到idle等待下一次接收
    } else {
        return sml::transition<class terminated>; // 返回转移到终止状态
    }
};

struct receiver_sm {
    auto operator()() const {
        using namespace sml;
        return make_transition_table(
            *state<class idle> + event<receive> / a_handle_receive = state<class reading>
            // reading状态会被动作返回的转移目标覆盖,无需额外定义
        );
    }
};

int main() {
    receiver_ctx ctx;
    sml::sm<receiver_sm> sm{ctx};

    sm.process_event(receive{30});
    sm.process_event(receive{40});
    sm.process_event(receive{40});

    return 0;
}

关键说明

  • 上下文的使用是避免重复计算的核心:所有需要复用的计算结果都存在上下文里,动作只做一次计算更新,守卫或后续逻辑直接读取。
  • 内部事件方案兼容性更好,适合C++17以下版本;动作返回转移目标的方式更简洁,是Boost SML推荐的现代写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:39:28