如何在不使用全类模板的情况下重构C++类型特定冗余操作
重构建议
以下几种方案可以避免代码重复,同时保持DataBase非模板类的约束:
方案一:提取通用实现函数(最小改动)
把重复的业务逻辑抽成一个模板私有函数,通过参数传递对应类型的缓存,do_something只需要根据类型分支调用这个通用函数:
#include <vector> #include <type_traits> struct DataBase { std::vector<double> cached; std::vector<double> cache2d; std::vector<float> cachef; std::vector<float> cache2f; // 更多同类型缓存... private: // 通用逻辑实现,接收所需的缓存引用 template<typename T> void do_something_impl(std::vector<T>& cache1, std::vector<T>& cache2 /*, 其他缓存参数*/) { // 这里写所有重复的业务逻辑,比如读写缓存、计算: if (!cache1.empty()) { T& val = cache1[0]; val += static_cast<T>(1.0); cache2.push_back(val * static_cast<T>(2.0)); } // 更多操作... } public: template <typename T> void do_something() { // 使用if constexpr确保编译时分支消除,无运行时开销 if constexpr (std::is_same_v<T, double>) { do_something_impl(cached, cache2d /*, 其他double缓存*/); } else if constexpr (std::is_same_v<T, float>) { do_something_impl(cachef, cache2f /*, 其他float缓存*/); } // 新增类型时只需添加对应分支 } };
方案二:打包同类型缓存(更整洁的结构)
将同类型的缓存打包成一个模板结构体,DataBase中存放不同类型的打包实例,通过辅助函数获取对应类型的缓存包,统一处理逻辑:
#include <vector> #include <type_traits> // 打包同类型的所有缓存 template<typename T> struct CacheBundle { std::vector<T> cache; std::vector<T> cache2; std::vector<T> cache3; // 扩展更多同类型缓存 // ... }; struct DataBase { CacheBundle<double> db_cache; CacheBundle<float> fb_cache; // 其他类型的缓存包... private: // 获取对应类型的缓存包引用 template<typename T> CacheBundle<T>& get_bundle(); // 特化double版本 template<> CacheBundle<double>& get_bundle<double>() { return db_cache; } // 特化float版本 template<> CacheBundle<float>& get_bundle<float>() { return fb_cache; } public: template <typename T> void do_something() { auto& bundle = get_bundle<T>(); // 统一处理逻辑,直接访问bundle中的缓存: bundle.cache.push_back(static_cast<T>(0.5)); bundle.cache2.push_back(bundle.cache.back() * static_cast<T>(3.0)); // 更多操作... } };
方案三:模板辅助类(适用于复杂逻辑)
如果业务逻辑非常复杂,可以用模板辅助类封装类型相关的操作,DataBase调用辅助类的静态方法:
#include <vector> #include <type_traits> struct DataBase { std::vector<double> cached; std::vector<double> cache2d; std::vector<float> cachef; std::vector<float> cache2f; // 更多缓存... private: // 模板辅助类,封装类型特定的缓存访问和逻辑 template<typename T> struct Helper; // double版本特化 template<> struct Helper<double> { static void execute(DataBase& db) { // 使用db的double缓存执行逻辑 db.cached.push_back(1.0); db.cache2d.push_back(db.cached.back() + 2.0); } }; // float版本特化 template<> struct Helper<float> { static void execute(DataBase& db) { // 使用db的float缓存执行逻辑 db.cachef.push_back(1.0f); db.cache2f.push_back(db.cachef.back() + 2.0f); } }; public: template <typename T> void do_something() { Helper<T>::execute(*this); } };
方案选择建议
- 如果现有代码结构不想大改,优先选方案一,改动最小且能消除重复代码;
- 如果缓存数量多、类型统一,优先选方案二,让代码结构更清晰,后续维护更方便;
- 如果逻辑复杂且需要封装更多类型相关操作,选方案三,隔离不同类型的实现细节。
内容的提问来源于stack exchange,提问作者HiroIshida
相关产品推荐
相关产品推荐

