C++模板类成员指针及const函数修改问题求解
解决方案
针对你的问题,我们可以通过两种思路解决,分别适配不同的通用性需求:
方案一:将SomeClass改为模板类(简单直接)
如果你的业务场景允许每个SomeClass实例仅处理一种特定类型,这是最简洁的实现方式:
#include <memory> #include <vector> template<typename T> class Holder { public: Holder() = default; ~Holder() = default; // 重载Add,分别处理左值和右值,避免错误移动原对象 void Add(T&& to_hold) { db.emplace_back(std::move(to_hold)); } void Add(const T& to_hold) { db.push_back(to_hold); } private: std::vector<T> db; }; template<typename T> class SomeClass { public: SomeClass() : holder_ptr(std::make_unique<Holder<T>>()) {} void DoSomething(T&& x) const { holder_ptr->Add(std::move(x)); } void DoSomething(const T& x) const { holder_ptr->Add(x); } private: // mutable允许const成员函数修改内部Holder对象 mutable std::unique_ptr<Holder<T>> holder_ptr; };
关键修复点:
- 将
SomeClass改为模板类,让holder_ptr的类型在编译期确定,解决模板成员变量的编译错误。 - 用
mutable修饰holder_ptr:因为Holder::Add需要修改内部vector,属于非const成员函数,而DoSomething是const成员函数,mutable允许在const上下文中修改该指针指向的对象。 - 修复原
Holder::Add的逻辑错误:原代码对左值引用使用std::move会意外移动原对象,重载左值/右值版本的Add可以避免这个问题。
方案二:类型擦除实现通用Holder(无模板SomeClass)
如果需要单个SomeClass实例能处理任意类型的对象,我们可以用类型擦除技术,让Holder内部自动维护不同类型的存储容器:
#include <memory> #include <vector> #include <any> #include <typeindex> #include <unordered_map> class Holder { public: template<typename T> void Add(T&& to_hold) { auto& vec = get_vector<T>(); vec.emplace_back(std::move(to_hold)); } template<typename T> void Add(const T& to_hold) { auto& vec = get_vector<T>(); vec.push_back(to_hold); } private: // 获取或创建对应类型的vector template<typename T> std::vector<T>& get_vector() { const auto type_idx = std::type_index(typeid(T)); if (!storage.contains(type_idx)) { storage[type_idx] = std::vector<T>(); } return std::any_cast<std::vector<T>&>(storage[type_idx]); } // 用type_index做键,存储任意类型的vector std::unordered_map<std::type_index, std::any> storage; }; class SomeClass { public: SomeClass() : holder_ptr(std::make_unique<Holder>()) {} template<typename T> void DoSomething(T&& x) const { holder_ptr->Add(std::move(x)); } template<typename T> void DoSomething(const T& x) const { holder_ptr->Add(x); } private: mutable std::unique_ptr<Holder> holder_ptr; };
关键优势:
SomeClass无需成为模板类,单个实例即可处理任意类型的对象,通用性更强。- 内部通过
std::type_index和std::any实现类型擦除,自动为每种类型维护独立的vector。 - 同样用
mutable保证const成员函数DoSomething可以修改内部存储。
内容的提问来源于stack exchange,提问作者user1673206
相关产品推荐
相关产品推荐

