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

如何基于多组可变参数模板列表调用模板函数

问题描述

现有模板函数:

template <typename T, typename U, typename V, typename W>
void MyFunc()
{
    // stuff...
}

需要针对给定的多组类型的所有组合调用该函数,具体类型组如下:

  • T: char, int, long long
  • U: float, double
  • V: std::uint64_t, std::string_view
  • W: int, MyEnum1, MyEnum2, MyEnum3

对应的伪代码逻辑为:

foreach (t in { char, int, long long })
{
    foreach (u in { float, double })
    {
        foreach (v in { std::uint64_t, std::string_view })
        {
            foreach (w in { int, MyEnum1, MyEnum2, MyEnum3 })
            {
                MyFunc<t, u, v, w>();
            }
        }
    }
}

已知可变参数模板、元组或「类型列表」等技巧可实现该需求,但未能梳理出具体方案,请问如何实现?

实现方案

方法1:C++17+ 用std::tuple+折叠表达式实现(推荐)

利用C++17的std::apply和折叠表达式,可以简洁遍历所有类型组合,无需手写递归模板:

#include <tuple>
#include <string_view>
#include <cstdint>
#include <type_traits>

// 定义所需枚举
enum class MyEnum1 {};
enum class MyEnum2 {};
enum class MyEnum3 {};

template <typename T, typename U, typename V, typename W>
void MyFunc()
{
    // 替换为你的实际业务逻辑
}

// 触发所有组合调用的入口函数
void invoke_all_combinations()
{
    // 用std::tuple存储各类型组的类型列表
    using TTypes = std::tuple<char, int, long long>;
    using UTypes = std::tuple<float, double>;
    using VTypes = std::tuple<std::uint64_t, std::string_view>;
    using WTypes = std::tuple<int, MyEnum1, MyEnum2, MyEnum3>;

    // 嵌套std::apply逐层展开每个类型组,最后用折叠表达式遍历W的所有类型
    std::apply([](auto... ts) {
        std::apply([ts...](auto... us) {
            std::apply([ts..., us...](auto... vs) {
                std::apply([ts..., us..., vs...](auto... ws) {
                    // 折叠表达式展开所有W类型,生成MyFunc的所有组合调用
                    (MyFunc<std::decay_t<decltype(ts)>, 
                            std::decay_t<decltype(us)>, 
                            std::decay_t<decltype(vs)>, 
                            std::decay_t<decltype(ws)>>(), ...);
                }, WTypes{});
            }, VTypes{});
        }, UTypes{});
    }, TTypes{});
}

方法2:兼容C11/C14 自定义类型列表+递归模板

如果需要支持更早的C++标准,可通过自定义类型列表配合递归模板逐层展开:

#include <string_view>
#include <cstdint>

enum class MyEnum1 {};
enum class MyEnum2 {};
enum class MyEnum3 {};

template <typename T, typename U, typename V, typename W>
void MyFunc()
{
    // 替换为你的实际业务逻辑
}

// 自定义类型列表结构
template <typename... Ts>
struct type_list {};

// 递归展开W类型组
template <typename T, typename U, typename V, typename WList>
struct call_w;

// 递归终止条件:空类型列表
template <typename T, typename U, typename V>
struct call_w<T, U, V, type_list<>>
{
    static void apply() {}
};

// 展开单个W类型,然后递归处理剩余W类型
template <typename T, typename U, typename V, typename W, typename... Ws>
struct call_w<T, U, V, type_list<W, Ws...>>
{
    static void apply()
    {
        MyFunc<T, U, V, W>();
        call_w<T, U, V, type_list<Ws...>>::apply();
    }
};

// 递归展开V类型组
template <typename T, typename U, typename VList, typename WList>
struct call_v;

template <typename T, typename U, typename WList>
struct call_v<T, U, type_list<>, WList>
{
    static void apply() {}
};

template <typename T, typename U, typename V, typename... Vs, typename WList>
struct call_v<T, U, type_list<V, Vs...>, WList>
{
    static void apply()
    {
        call_w<T, U, V, WList>::apply();
        call_v<T, U, type_list<Vs...>, WList>::apply();
    }
};

// 递归展开U类型组
template <typename T, typename UList, typename VList, typename WList>
struct call_u;

template <typename T, typename VList, typename WList>
struct call_u<T, type_list<>, VList, WList>
{
    static void apply() {}
};

template <typename T, typename U, typename... Us, typename VList, typename WList>
struct call_u<T, type_list<U, Us...>, VList, WList>
{
    static void apply()
    {
        call_v<T, U, VList, WList>::apply();
        call_u<T, type_list<Us...>, VList, WList>::apply();
    }
};

// 递归展开T类型组,触发所有组合调用
template <typename TList, typename UList, typename VList, typename WList>
struct call_all;

template <typename UList, typename VList, typename WList>
struct call_all<type_list<>, UList, VList, WList>
{
    static void apply() {}
};

template <typename T, typename... Ts, typename UList, typename VList, typename WList>
struct call_all<type_list<T, Ts...>, UList, VList, WList>
{
    static void apply()
    {
        call_u<T, UList, VList, WList>::apply();
        call_all<type_list<Ts...>, UList, VList, WList>::apply();
    }
};

// 主调用入口
void invoke_all_combinations()
{
    using TTypes = type_list<char, int, long long>;
    using UTypes = type_list<float, double>;
    using VTypes = type_list<std::uint64_t, std::string_view>;
    using WTypes = type_list<int, MyEnum1, MyEnum2, MyEnum3>;

    call_all<TTypes, UTypes, VTypes, WTypes>::apply();
}

关键说明

  • 两种方法都会生成3*2*2*4=48种类型组合的MyFunc实例,覆盖所有需求中的类型组合。
  • 方法1依赖C17特性,代码简洁易维护,是现代C的首选方案。
  • 方法2通过递归模板实现,兼容C++11及以上标准,适合旧项目场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:34:53