C++可变参数模板实现去重多类型数组管理类及重载方法是否可行?
实现方案
该需求完全可实现,以下是基于C++17标准的低冗余、易读实现方案,不需要手动为每个类型声明成员变量,自动完成类型去重校验。
核心实现思路
- 用可变参数模板接收所有传入的结构体类型,通过编译期类型校验保证无重复类型
- 用
std::tuple存储对应类型的std::vector实例,利用C++17的折叠表达式和按类型取tuple元素的特性,实现按类型快速获取对应数组 - 泛型
process方法通过模板参数匹配对应数组,完成遍历操作
完整代码实现
#include <vector> #include <tuple> #include <type_traits> #include <functional> // 编译期校验所有类型是否不重复 template <typename T, typename... Rest> constexpr bool is_unique_type = (!std::is_same_v<T, Rest> && ...); template <typename... Ts> constexpr bool all_types_unique = (is_unique_type<Ts, Ts...> && ...); // C++20版本,用requires做模板约束 template <typename... Ts> requires all_types_unique<Ts...> class Manager { private: std::tuple<std::vector<Ts>...> m_vectors; public: // 获取对应类型的数组引用 template <typename T> std::vector<T>& get_vector() { return std::get<std::vector<T>>(m_vectors); } // 处理方法,支持传入自定义处理回调 template <typename T, typename Func> void process(Func&& func) { auto& vec = get_vector<T>(); for (auto& elem : vec) { std::invoke(std::forward<Func>(func), elem); } } // 也可按需实现无回调的默认process逻辑 // template <typename T> // void process() { // // 自定义默认处理逻辑 // } }; // 若使用C++17及更低版本,不支持requires语法,可替换为以下实现,用静态断言做校验: // template <typename... Ts> // class Manager { // static_assert(all_types_unique<Ts...>, "Manager的模板参数不能有重复类型"); // private: // std::tuple<std::vector<Ts>...> m_vectors; // public: // // 其余方法和上面实现完全一致 // };
使用示例
// 自定义结构体 struct A { int a; }; struct B { int b; }; int main() { // 合法实例化:无重复类型 Manager<A, B> mgr; // 非法实例化:重复类型,编译期直接报错 // Manager<A, A, B> invalid_mgr; // 往对应数组添加元素 mgr.get_vector<A>().push_back({1}); mgr.get_vector<A>().push_back({2}); mgr.get_vector<B>().push_back({10}); // 按类型处理A数组的所有元素 mgr.process<A>([](A& elem) { elem.a += 10; // 自定义处理逻辑 }); // 按类型处理B数组的所有元素 mgr.process<B>([](B& elem) { elem.b *= 2; }); return 0; }
方案优势
- 无冗余代码:不需要手动为每个模板参数声明对应成员变量,新增类型只需要在Manager的模板参数里添加即可
- 编译期校验:重复类型的非法实例化会在编译阶段直接报错,无运行时开销
- 易扩展:process方法支持传入任意自定义回调,不需要修改Manager类的代码就能适配不同的处理逻辑
内容的提问来源于stack exchange,提问作者ZeroZ30o
相关产品推荐
相关产品推荐

