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

C++17下简化std::tuple状态机transit_to函数的样板代码

问题描述

我在实现有限状态机时,将所有可用状态存储在std::tuple中,原有代码通过手写if分支实现运行时索引到模板实例的分发,每次新增状态都需要手动补充分支,存在重复样板代码。
原有示例代码逻辑如下:

#include <tuple>
#include <stdio.h>

struct state1 {};
struct state2 {};
struct state3 {};
struct state4 {};

std::tuple<state1, state2, state3, state4> states;

template<size_t Index>
void transit_to()
{
    auto state = std::get<Index>(states);
    // 执行状态切换相关逻辑
}

void transit_to(size_t index)
{
    if (index == 0) return transit_to<0>();
    if (index == 1) return transit_to<1>();
    if (index == 2) return transit_to<2>();
    if (index == 3) return transit_to<3>();
}

int main()
{
    for(int i=0; i<=3; ++i)
        transit_to(i);
}

改造需要满足两个约束:

  • 仅使用C17及更低版本的标准特性,禁止使用C20新增语法
  • 不修改原有对外接口,不接受改为通过类型访问状态等接口调整方案
实现方案

借助C++17的折叠表达式和std::index_sequence工具,可以自动生成所有索引的分发逻辑,后续新增状态时只需要往tuple里追加类型,不需要手动写分支判断。
完整可运行代码如下:

#include <tuple>
#include <cstdio>
#include <utility>

struct state1 {};
struct state2 {};
struct state3 {};
struct state4 {};

std::tuple<state1, state2, state3, state4> states;

template<size_t Index>
void transit_to()
{
    auto state = std::get<Index>(states);
    // 原有状态处理逻辑保持不变
}

// 内部分发辅助函数,不对外暴露
template<size_t... Indices>
void transit_to_impl(size_t index, std::index_sequence<Indices...>)
{
    // 折叠表达式自动展开生成所有索引的判断分支,匹配到对应索引就调用对应模板实例
    ((index == Indices && (transit_to<Indices>(), true)) || ...);
}

void transit_to(size_t index)
{
    // 自动获取状态tuple的长度,生成0到长度-1的连续索引序列
    transit_to_impl(index, 
        std::make_index_sequence<std::tuple_size_v<decltype(states)>>{});
}

int main()
{
    for(int i=0; i<=3; ++i)
        transit_to(i);
}

方案特性

  • 完全兼容原有接口:对外暴露的两个transit_to函数签名和原有代码完全一致,上层调用逻辑不需要任何修改
  • 零额外开销:编译器优化后生成的汇编代码和手写if分支完全相同,没有运行时性能损失
  • 符合版本要求:用到的std::index_sequence是C14标准特性,折叠表达式、std::tuple_size_v是C17标准特性,没有使用任何C++20新增语法
  • 免维护:后续新增、删除状态时,只需要修改states元组的类型列表,不需要手动调整运行时分发的分支代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:54:19