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

不修改Runner模板类前提下,能否遍历模板类列表?

不修改Runner的前提下遍历模板类列表调用dosomething方法

首先明确你的场景:现有不可修改的Runner模板类,需要遍历一组模板类(A、B、C),逐个调用runner.dosomething<X>()。

你的现有代码

Runner类定义

template<typename T>
struct Runner  {
    template<template<typename> typename U>
    auto dosomething() {
        U<T> u; // 用模板参数T实例化传入的模板类U
    }
};

手动调用示例

template<typename T> struct A {};
template<typename T> struct B {};
template<typename T> struct C {};

int main()
{
    Runner<int> runner;
    runner.dosomething<A>();
    runner.dosomething<B>();
    runner.dosomething<C>();
}

需求与遇到的问题

你希望将A、B、C封装成模板类列表,通过遍历实现批量调用,伪代码如下:

// 伪代码(C++中无法直接运行)
using typelist = magictypelist<A,B,C>;
typelist::iterate ([&] <typename X> { 
    runner.dosomething<X>();
});

尝试过用std::tuple存储实例化后的类型,但无法从A<T>这类具体类型中还原出原始模板类A,因此无法匹配dosomething所需的模板类参数。


解决方案:自定义模板类列表容器+编译期遍历

我们可以通过模板元编程定义专门存储模板类的容器,再配合编译期遍历实现需求,完全不需要修改Runner类。

1. 定义模板类列表容器

这个容器直接存储模板类模板,而非具体类型:

// 模板类列表容器,接受任意数量的单参数模板类
template<template<typename> typename... Ts>
struct TemplateList {};

用TemplateList<A, B, C>即可表示你的模板类列表。

2. 实现遍历调用逻辑

根据C++版本选择不同实现方式:

方式一:C++17及以上(折叠表达式,简洁高效)
// 通用遍历函数,支持任意类型的Runner实例
template<typename RunnerInstance, template<typename> typename... Ts>
void iterate_template_list(RunnerInstance& runner, TemplateList<Ts...>) {
    // 折叠表达式展开,逐个调用dosomething
    (runner.template dosomething<Ts>(), ...);
}

注意:runner.template dosomething<Ts>()中的template关键字是必须的——因为RunnerInstance是模板参数,编译器无法自动推断dosomething是模板函数,需要显式指明。

方式二:C11/C14兼容(递归模板特化)
// 递归终止条件:空列表
template<typename RunnerInstance>
void iterate_template_list(RunnerInstance&, TemplateList<>) {}

// 递归展开:处理第一个模板类,再递归处理剩余列表
template<typename RunnerInstance, template<typename> typename First, template<typename> typename... Rest>
void iterate_template_list(RunnerInstance& runner, TemplateList<First, Rest...>) {
    runner.template dosomething<First>();
    iterate_template_list(runner, TemplateList<Rest...>());
}

3. 使用示例

int main() {
    Runner<int> runner;
    // 定义你的模板类列表
    using MyTemplateList = TemplateList<A, B, C>;
    // 遍历调用
    iterate_template_list(runner, MyTemplateList{});
    
    // 也支持其他类型的Runner
    Runner<double> d_runner;
    iterate_template_list(d_runner, MyTemplateList{});
}

运行这段代码后,会自动依次调用runner.dosomething<A>()、runner.dosomething<B>()、runner.dosomething<C>(),完全符合你的需求。


原理说明

TemplateList直接存储模板类模板(比如A),而dosomething需要的参数正好是template<typename> typename U类型的模板类,因此可以直接传递。相比用std::tuple存储具体类型的方案,这种方式不需要从实例化后的类型中反向提取模板类,逻辑更直接,也完全适配Runner的API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:05:54