C++如何使用std::variant实现状态机?(代码示例)

admin 百科 12
用std::variant实现状态机的核心思路是将各状态建模为独立轻量类型(如空结构体或含数据的小结构),用variant持有当前状态,并通过std::visit分发处理逻辑,实现类型安全、无虚函数、无动态分配的状态机。

C++如何使用std::variant实现状态机?(代码示例)-第1张图片-佛山资讯网

std::variant 实现状态机,核心思路是把每个状态建模为一个独立的、无状态的类型(如空结构体或带数据的小结构),再用 std::variant 持有当前状态。配合 std::visit 分发处理逻辑,能写出类型安全、无虚函数、无动态分配的状态机。

定义状态类型

每个状态用一个轻量级类型表示,推荐使用空结构体(语义清晰)或含必要数据的结构体(如等待超时时间、缓存值等):

struct Idle {};
struct Connecting { std::string host; int port; };
struct Connected { int socket_fd; };
struct Error { std::string message; };

登录后复制

然后组合成 variant:

using State = std::variant<Idle, Connecting, Connected, Error>;

登录后复制

封装状态机类

State 封装在类中,并提供状态转换与行为分发接口:

立即学习“C++免费学习笔记(深入)”;

class NetworkStateMachine {
private:
    State state_ = Idle{};
<p>public:
void connect(const std::string& host, int port) {
std::visit(overloaded{
<a href="https://www.php.cn/link/b0c01f1f6d5e54fbd6a1bfff163acb60">&</a> { state<em> = Connecting{host, port}; },
<a href="https://www.php.cn/link/cc11d15b3f413bf76897f2b8cff222fa">&</a> { /<em> 忽略重复调用 </em>/ },
<a href="https://www.php.cn/link/1e60bf71283dac0b8777b83250813e56">&</a> { /<em> 已连接,可选择断开再连 </em>/ },
[&](Error&& e) { state</em> = Connecting{host, port}; } // 重试
}, state_);
}</p><pre class="brush:php;toolbar:false;">void on_connected(int fd) {
    std::visit(overloaded{
        [&](https://www.php.cn/link/cc11d15b3f413bf76897f2b8cff222fa c) { state_ = Connected{fd}; },
        [&](auto&&) { /* 其他状态不响应 */ }
    }, state_);
}

void on_error(std::string msg) {
    std::visit(overloaded{
        [&](https://www.php.cn/link/cc11d15b3f413bf76897f2b8cff222fa c) { state_ = Error{std::move(msg)}; },
        [&](https://www.php.cn/link/1e60bf71283dac0b8777b83250813e56 c) { state_ = Error{std::move(msg)}; },
        [&](auto&&) { /* Idle 或 Error 不变 */ }
    }, state_);
}

登录后复制

};

其中 overloaded 是常见辅助工具(C++17 起可直接用 lambda 重载):

标签: 工具 mac ai c++

发布评论 0条评论)

还木有评论哦,快来抢沙发吧~