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

用 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 重载):
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~