C++能否对多个参数包同时递归?具体该如何实现?
C++双参数包同步展开的实现方案
结论
完全可以实现,C++11及以上版本都支持多个参数包的同步递归/展开操作,只要保证两个参数包长度一致即可一一对应取值。
具体实现
方案1:递归版本(兼容C++11,和你原有实现风格一致)
和你原有单参数包递归的逻辑类似,我们通过索引下标同步取两个参数包的对应元素,实现递归继承:
#include <tuple> #include <array> // 递归主模板:从第Idx位开始展开两个参数包 template<template<typename, const char*> class C, size_t Idx, typename... Ts, const char*... Ns> struct InheritRecursive : public C<typename std::tuple_element<Idx, std::tuple<Ts...>>::type, std::get<Idx>(std::array<const char*, sizeof...(Ns)>{Ns...})> , public InheritRecursive<C, Idx + 1, Ts..., Ns...> {}; // 递归终止特化:索引等于参数包长度时停止递归 template<template<typename, const char*> class C, typename... Ts, const char*... Ns> struct InheritRecursive<C, sizeof...(Ts), Ts..., Ns...> {}; // 对外暴露的别名模板,简化调用 template<template<typename, const char*> class C, typename... TsAndNs> struct Inherit; // 偏特化拆分参数包为类型序列和字符串指针序列 template<template<typename, const char*> class C, typename... Ts, const char*... Ns> struct Inherit<C, Ts..., Ns...> { static_assert(sizeof...(Ts) == sizeof...(Ns), "类型参数包和字符串参数包长度必须一致"); using type = InheritRecursive<C, 0, Ts..., Ns...>; }; template<template<typename, const char*> class C, typename... TsAndNs> using Inherit_t = typename Inherit<C, TsAndNs...>::type;
方案2:非递归展开(C++14及以上,代码更简洁)
直接利用参数包展开语法一次性继承所有实例化的接口,不需要递归逻辑:
#include <tuple> #include <utility> template<template<typename, const char*> class C, typename... Ts, const char*... Ns, size_t... Idx> struct InheritHelper<std::index_sequence<Idx...>, C, Ts..., Ns...> : public C<typename std::tuple_element<Idx, std::tuple<Ts...>>::type, std::get<Idx>(std::array<const char*, sizeof...(Ns)>{Ns...})>... {}; template<template<typename, const char*> class C, typename... TsAndNs> struct Inherit; template<template<typename, const char*> class C, typename... Ts, const char*... Ns> struct Inherit<C, Ts..., Ns...> { static_assert(sizeof...(Ts) == sizeof...(Ns), "类型参数包和字符串参数包长度必须一致"); using type = InheritHelper<std::make_index_sequence<sizeof...(Ts)>, C, Ts..., Ns...>; }; template<template<typename, const char*> class C, typename... TsAndNs> using Inherit_t = typename Inherit<C, TsAndNs...>::type;
使用示例
按照你的需求,Example类的写法如下:
// 你的双参数接口模板 template<typename T, const char* N> class Interface { // 接口实现逻辑 }; // 对外的Example类模板 template<typename... Ts, const char*... Ns> class Example : public Inherit_t<Interface, Ts..., Ns...> { // Example类实现逻辑 }; // 测试用的全局字符串常量(必须具备外部链接) extern const char name_int[] = "int"; extern const char name_float[] = "float"; // 实例化使用 Example<int, float, name_int, name_float> test_obj; // test_obj 会同时继承 Interface<int, name_int> 和 Interface<float, name_float>
注意事项
- C++20之前,作为模板参数的
const char*必须是具备外部链接的全局常量,不能直接传递字符串字面量。 - 代码中已经添加了静态断言校验两个参数包的长度,避免传参错误。
内容的提问来源于stack exchange,提问作者Nick Vanbaelen
相关产品推荐
相关产品推荐

