文档目录

一、解决什么问题?

std::tuple 的元素类型不同,不能用普通 for 循环遍历。

需求:我想对 tuple 的每个元素调用同一函数。

std::tuple<int, double, std::string> t = {1, 2.0, "hello"};
// 我想实现:
// print(get<0>(t));
// print(get<1>(t));
// print(get<2>(t));
// 但不能写 for (int i = 0; i < 3; i++) print(get<i>(t)); ← 编译 error,i 不是编译期常量

二、if constexpr + 递归——编译期循环

template <typename Tuple, typename Func, size_t I = 0>
void tuple_for_each(const Tuple& t, Func&& f) {
    if constexpr (I < std::tuple_size_v<Tuple>) {
        f(std::get<I>(t));                             // 处理第 I 个元素
        tuple_for_each<Tuple, Func, I + 1>(t,           // 递归处理下一个
                                           std::forward<Func>(f));
    }
    // if constexpr 的关键:当 I >= tuple_size 时,
    // 这个递归调用分支的代码直接被编译器丢弃,
    // 不会产生无限递归!
}

编译器展开:

tuple_for_each(t, f, 0)
  if constexpr (0 < 3) → true
    f(get<0>(t))
    tuple_for_each(t, f, 1)
      if constexpr (1 < 3) → true
        f(get<1>(t))
        tuple_for_each(t, f, 2)
          if constexpr (2 < 3) → true
            f(get<2>(t))
            tuple_for_each(t, f, 3)
              if constexpr (3 < 3) → false
                // 整个递归调用分支被丢弃!不生成代码

最终生成的代码等价于:

f(get<0>(t));
f(get<1>(t));
f(get<2>(t));

零运行时开销——完全展开为 3 条语句。

三、什么时候需要手写 tuple 遍历?

场景 示例
序列化库 把 tuple<int, double, string> 按顺序写到文件
GUI 属性绑定 遍历元组生成 QLabel 列表
反射替代 遍历结构体成员做批量校验
策略合并 tuple 里放了多个策略对象,遍历执行它们

四、第五阶段总结——一张表记住

技巧 解决什么问题 替代了什么 是否常用
CRTP 编译期多态,消除虚函数开销 虚函数继承 写库时常用
Variadic Templates 类型安全的任意参数 va_args/重载 天天用
Fold Expressions 参数包的简化操作 递归模板 C++17 后常用
index_sequence tuple 展开为参数 无 面试常考
tuple 遍历 异质容器逐元素操作 无 序列化等场景