如何在未知类型时声明Object模板指针?C++模板类型推导问题
问题:获取模板类型中的Object指针
编写了一段包含模板函数的代码,函数可接收继承自Object类或能通过运算符提供Object实例指针的对象。在函数内部需要获取Object指针,但由于是模板类型,无法确定如何指定模板类型。尝试过使用value_type,但因存在两种输入对象类型而无效;还尝试为函数模板添加额外参数,但编译器无法推导参数类型。
代码示例
class IObject { }; template<class T> class Object: public IObject { typedef T value_type; public: void test() { } operator Object<T>*() { return this; } }; template<class T> class Wrapper { typedef T value_type; public: T object; operator T*() { return &object; } }; template<class T> class Container { public: void func() { data.resize(1); typename T::value_type& ref = data[0]; //IObject* object = ref; //works Object<?>* object = ref; // How can I specify the template type here? object->test(); }; T data; }; int main() { Container<std::vector<Object<float>>> container1; container1.func(); Container<std::vector<Wrapper<Object<int>>>> container2; container2.func(); return 0; }
解决方案
方案1:类型萃取(Type Traits)
定义类型萃取模板,统一提取Object的模板参数类型,适配Object<T>和Wrapper<Object<T>>两种输入类型:
// 基础类型萃取,处理Object<T> template<typename U> struct ObjectTypeExtractor { using type = typename U::value_type; }; // 特化版本,处理Wrapper<Object<T>> template<typename U> struct ObjectTypeExtractor<Wrapper<U>> { using type = typename U::value_type; };
修改Container的func函数:
void func() { data.resize(1); typename T::value_type& ref = data[0]; // 提取Object的模板参数类型 using ObjectValueType = typename ObjectTypeExtractor<typename T::value_type>::type; Object<ObjectValueType>* object = ref; object->test(); }
方案2:利用C++11的auto自动推导
直接让编译器推导指针类型,无需手动指定模板参数:
void func() { data.resize(1); auto& ref = data[0]; auto object = ref; // 借助重载的operator*自动推导类型 object->test(); }
或者结合decltype明确推导:
void func() { data.resize(1); typename T::value_type& ref = data[0]; auto object = static_cast<decltype(ref)>(ref); object->test(); }
方案3:多态接口(最简洁)
将test()声明为IObject的虚函数,利用多态特性直接调用,无需关心具体的Object模板类型:
修改IObject类:
class IObject { public: virtual void test() = 0; virtual ~IObject() = default; // 必须添加虚析构,避免内存泄漏 };
修改Object类实现虚函数:
template<class T> class Object: public IObject { typedef T value_type; public: void test() override // 标记override确保重写正确 { } operator Object<T>*() { return this; } };
此时Container的func可以直接使用IObject指针:
void func() { data.resize(1); typename T::value_type& ref = data[0]; IObject* object = ref; object->test(); // 多态调用对应类型的test() }
内容的提问来源于stack exchange,提问作者Dmitry Logov
相关产品推荐
相关产品推荐

