如何遍历C++可变参数模板类型列表并调用对应模板函数?
这是个很常见的需求,针对不同C++版本,咱们有几种简洁的实现方式,我给你一一拆解:
方法1:C++17及以上 - 折叠表达式(最简洁)
C++17引入的折叠表达式是处理可变参数模板最直观的方式,一行代码就能搞定展开:
#include <utility> // 你的类型列表定义 template <typename ... Types> struct tl {}; using my_list = tl<MyTypeA, MyTypeB, MyTypeC>; // 假设的模板函数 template <typename T> void myFunc() { // 这里是你的函数逻辑,比如打印类型名或者做其他操作 } // 批量调用的函数 template <typename... Types> void call_myFunc(tl<Types...>) { // 逗号折叠表达式:依次对每个Types调用myFunc<Types>() (myFunc<Types>(), ...); } // 使用方式 int main() { call_myFunc(my_list{}); // 会依次调用myFunc<MyTypeA>(), myFunc<MyTypeB>(), myFunc<MyTypeC>() return 0; }
这里的逗号折叠会把可变参数逐个展开,按顺序执行每个myFunc调用,哪怕myFunc返回void也能正常工作。
方法2:C11/C14 - 递归模板展开
如果你的项目还停留在C++17之前的版本,可以用递归模板来逐个处理类型列表:
#include <utility> template <typename ... Types> struct tl {}; using my_list = tl<MyTypeA, MyTypeB, MyTypeC>; template <typename T> void myFunc() { /* 你的逻辑 */ } // 递归终止条件:空类型列表 void call_myFunc(tl<>) {} // 递归展开:处理第一个类型,然后递归处理剩余类型 template <typename First, typename... Rest> void call_myFunc(tl<First, Rest...>) { myFunc<First>(); call_myFunc(tl<Rest...>()); } // 使用方式 int main() { call_myFunc(my_list{}); return 0; }
这种方式的核心是通过模板特化定义空列表的终止函数,然后每次递归剥离第一个类型,直到列表为空。
方法3:C++11及以上 - 初始化列表技巧(非递归)
如果你不想用递归,还可以利用初始化列表的副作用来展开调用,同样适用于C++11:
#include <utility> template <typename ... Types> struct tl {}; using my_list = tl<MyTypeA, MyTypeB, MyTypeC>; template <typename T> void myFunc() { /* 你的逻辑 */ } template <typename... Types> void call_myFunc(tl<Types...>) { // 用dummy数组触发每个调用,逗号表达式确保先执行myFunc再返回0 using dummy = int[]; (void)dummy{0, (myFunc<Types>(), 0)...}; } // 使用方式 int main() { call_myFunc(my_list{}); return 0; }
这里的原理是:初始化列表会按顺序计算每个元素,(myFunc<Types>(), 0)会先执行myFunc,然后返回0作为数组元素。(void)转换是为了避免编译器对未使用数组的警告。
内容的提问来源于stack exchange,提问作者Waldorf
相关产品推荐
相关产品推荐

