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

关于Boost SML库中on_entry、on_exit及_类型的技术疑问

Understanding Boost SML's on_entry, on_exit, and the _ Placeholder

Hey there! Let me break down these Boost SML concepts for you clearly—they can feel a bit opaque at first, but once you see how they fit into state machine logic, it all clicks.

1. The struct _ {} Placeholder

First, that struct _ {} is Boost SML's way of saying "match anything". It's a generic placeholder used in two common scenarios:

  • Matching any event: When you want a state transition to trigger regardless of what event is received, use event<_> in your transition table.
  • Default actions/conditions: It can also act as a fallback for cases where you don't need to specify a specific event or guard.

Example of using _ for any event:

// Transition from Running to Idle no matter what event comes in
sml::state<Running> + sml::event<_> = sml::state<Idle>

2. on_entry: Logic When Entering a State

on_entry is a lifecycle hook that runs the moment your state machine enters a specific state. It's perfect for initialization tasks like setting up resources, logging, or updating context data.

How to Use It

You can pass a function object, lambda, or regular function to on_entry<>:

  • Function Object: Define a struct with an operator() that takes optional parameters (the triggering event, state machine context, etc.)
    struct idle_entry_handler {
      void operator()(const auto& triggering_event, my_context& ctx) {
        // Initialize resources, log entry, or update context
        std::cout << "Entered Idle state via event: " << typeid(triggering_event).name() << "\n";
        ctx.is_idle = true;
      }
    };
    
    // In your transition table:
    *sml::state<Idle> + sml::on_entry<idle_entry_handler>
    
  • Lambda (Shorter Syntax): For simple logic, use a lambda directly:
    sml::state<Running> + sml::on_entry([](my_context& ctx) {
      ctx.running_counter++;
      std::cout << "Starting operation " << ctx.running_counter << "\n";
    })
    

Template Logic

The on_entry template is designed to be flexible—it automatically deduces the parameters your callback accepts. You can omit the event if you don't care what triggered the entry, or omit the context if you don't need to modify state machine data.

3. on_exit: Logic When Leaving a State

on_exit is the mirror of on_entry—it runs right before the state machine leaves a state. Use it for cleanup tasks like releasing resources, saving state, or logging exit.

Usage Examples

  • Basic Cleanup Lambda:
    sml::state<Running> + sml::on_exit([]() {
      std::cout << "Shutting down running operations\n";
      // Release any temporary resources here
    })
    
  • Context-Aware Handler:
    struct running_exit_handler {
      void operator()(my_context& ctx) {
        ctx.last_run_time = std::chrono::steady_clock::now();
        std::cout << "Exited Running state at " << ctx.last_run_time.time_since_epoch().count() << "\n";
      }
    };
    
    // In transition table:
    sml::state<Running> + sml::on_exit<running_exit_handler>
    

Putting It All Together: A Mini Example

Here's a concise state machine that uses all three concepts:

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

namespace sml = boost::sml;

// Events
struct start {};
struct pause {};
struct unknown_event {};

// Context
struct app_ctx {
  int session_count = 0;
};

// State handlers
struct active_entry {
  void operator()(const start&, app_ctx& ctx) {
    ctx.session_count++;
    std::cout << "Starting session #" << ctx.session_count << "\n";
  }
};

struct active_exit {
  void operator()() {
    std::cout << "Pausing active session\n";
  }
};

// Transition table
auto app_machine = sml::make_transition_table(
  *sml::state<class Idle>
  + sml::event<start> = sml::state<class Active>
  , sml::state<Active> + sml::on_entry<active_entry> + sml::on_exit<active_exit>
  + sml::event<pause> = sml::state<Idle>
  // Catch any other event to go back to Idle
  + sml::event<_> = sml::state<Idle>
);

int main() {
  app_ctx ctx;
  sml::sm<decltype(app_machine)> sm{app_machine, ctx};

  sm.process_event(start{});    // Enters Active, triggers active_entry
  sm.process_event(unknown_event{}); // Triggers active_exit, goes back to Idle
}

When you run this, you'll see:

Starting session #1
Pausing active session

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:56:58