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

如何遍历类型名列表的所有组合并调用模板函数?

遍历类型列表的所有组合并处理

要实现编译期遍历类型列表的所有笛卡尔积组合,核心是利用编译期整数序列展开——因为运行期循环变量无法作为模板参数传递。下面提供几种可行方案:

方案1:递归展开(C++11及以上)

通过递归逐个处理每个外层类型,再递归处理内层的每个类型,覆盖所有组合:

#include <iostream>
#include <limits>
#include <tuple>
#include <cstdint>

template<typename T, typename R>
void foo() {
    std::cout << std::numeric_limits<T>::max() << ", " << std::numeric_limits<R>::max() << '\n';
}

// 处理单个外层类型T与所有内层类型
template<typename T, typename Tuple, size_t... Js>
void process_inner(std::index_sequence<Js...>) {
    (foo<T, std::tuple_element_t<Js, Tuple>>(), ...); // C++17折叠表达式,简化展开逻辑
}

// 遍历所有外层类型
template<typename Tuple, size_t... Is>
void process_outer(std::index_sequence<Is...>) {
    (process_inner<std::tuple_element_t<Is, Tuple>, Tuple>(std::make_index_sequence<std::tuple_size_v<Tuple>>()), ...);
}

void call() {
    using int_types = std::tuple<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>;
    process_outer<int_types>(std::make_index_sequence<std::tuple_size_v<int_types>>());
}

int main() {
    call();
    return 0;
}

如果是C++11(不支持折叠表达式),可以把内层展开改成递归模板:

// C++11版本内层递归辅助模板
template<typename T, typename Tuple, size_t J>
struct inner_helper {
    static void call() {
        foo<T, std::tuple_element_t<J-1, Tuple>>();
        inner_helper<T, Tuple, J-1>::call();
    }
};

template<typename T, typename Tuple>
struct inner_helper<T, Tuple, 0> {
    static void call() {}
};

template<typename T, typename Tuple>
void process_inner_cpp11() {
    inner_helper<T, Tuple, std::tuple_size<Tuple>::value>::call();
}

// 外层递归同理修改即可

方案2:C++20模板lambda简化写法

利用C++20的模板lambda,省去额外的递归函数,代码更紧凑:

#include <iostream>
#include <limits>
#include <tuple>
#include <cstdint>
#include <utility>

template<typename T, typename R>
void foo() {
    std::cout << std::numeric_limits<T>::max() << ", " << std::numeric_limits<R>::max() << '\n';
}

void call() {
    using int_types = std::tuple<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t>;
    constexpr auto size = std::tuple_size_v<int_types>;

    // 展开外层索引
    [&]<size_t... Is>(std::index_sequence<Is...>) {
        (
            // 展开内层索引
            [&]<size_t... Js>(std::index_sequence<Js...>) {
                (foo<std::tuple_element_t<Is, int_types>, std::tuple_element_t<Js, int_types>>(), ...);
            }(std::make_index_sequence<size>()),
            ...
        );
    }(std::make_index_sequence<size>());
}

int main() {
    call();
    return 0;
}

核心原理说明

  • std::index_sequence和std::make_index_sequence生成编译期整数序列,序列中的每个值都是编译期常量,可安全作为std::tuple_element_t的模板参数。
  • 折叠表达式(C++17+)替代递归模板,大幅简化展开逻辑。
  • 模板lambda(C++20+)允许在lambda内部使用模板参数,无需额外定义辅助函数或模板,代码结构更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:48:21