如何在容器中存储不同类型的模板化对象
How to store templated objects of different type in container?
假设我有一个vector
(或list
或任何更适合这里的容器),我想将模板化类型的多个对象(或指针)存储在:中
std::vector<MyClass<double>> v;
// std::vector<MyClass<double> *> v;
不幸的是,我想在这个容器中存储不同的模板化对象(理想情况下,我需要在恒定时间访问它们)。
我的第一直觉是围绕MyClass
创建某种WrapperClass
,它将在内部管理任何MyClass
作为成员变量,但我不清楚如何将适当的类型传递给MyClass
:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
template<typename T>
class MyClass
{
public:
MyClass() {}
~MyClass() {}
};
// templating this of course works, but it doesn't solve my problem
template<typename T>
class WrapperClass
{
public:
WrapperClass()
{
m_object = MyClass<T>();
}
~WrapperClass() { }
private:
MyClass<T> m_object;
};
int main()
{
WrapperClass<bool> tmp = WrapperClass<bool>();
std::vector<WrapperClass<bool> *> v;
return 0;
}
那么,是否有(A)一个与vector
不同的容器可以用于解决此问题,或者有在构造函数内的WrapperClass
中选择MyClass
类型的方法?我想的是:
class WrapperClass2
{
public:
WrapperClass2(unsigned int typeId)
{
switch (typeId)
{
case 0: m_object = new MyClass<bool>();
case 1: m_object = new MyClass<int>();
case 2: m_object = new MyClass<float>();
default: m_object = new MyClass<double>();
}
}
~WrapperClass2()
{
delete m_object;
}
private:
MyClass * m_object;
};
另一个想法可能是在向量中使用一些父AbstractType
,但我不确定这对模板化类型问题有什么帮助。
类模板的不同实例化是完全不相关的类型,因此不能有直接存储它们的容器。
你有几个选择:
- 保留指向类模板从中继承的某个基类的指针集合:
class Base
{
virtual ~Base {}
virtual void someMethod() const = 0;
};
template <typename T>
class MyClass : public Base
{
void someMethod() const
{
// stuff
}
};
int main()
{
std::vector<std::unique_ptr<Base>> objs;
objs.push_back(std::make_unique<MyClass<int>>());
objs.push_back(std::make_unique<MyClass<std::string>>());
for (auto& i : objs) {
i->someMethod();
}
}
这是一种相当简单的方法,但它会因动态分配和RTTI而产生一些运行时开销。还要注意,someMethod
不能返回T
,因为它是父类上的一个方法,不知道T
是什么
- 使用某种类型擦除的包装器,如
boost::any
(或C++17中即将推出的std::any
)
#include <any>
#include <string>
#include <vector>
template <typename T>
class MyClass {
public:
T someMethod() const {
// stuff
return {};
}
};
void someFunctionThatTakesInt(int i) {}
void someFunctionThatTakesString(std::string s) {}
int main() {
std::vector<std::any> objs;
objs.push_back(MyClass<int>());
objs.push_back(MyClass<std::string>());
for (const auto& i : objs) {
if (i.type() == typeid(MyClass<int>)) {
auto& mc = std::any_cast<const MyClass<int>&>(i);
someFunctionThatTakesInt(mc.someMethod());
} else if (i.type() == typeid(MyClass<std::string>)) {
auto& mc = std::any_cast<const MyClass<std::string>&>(i);
someFunctionThatTakesString(mc.someMethod());
}
}
}
这种方法意味着您可以让someMethod
返回T
,但会使从vector
检索对象变得更加困难,因为您必须先弄清楚它们是什么类型,然后才能对它们执行任何操作(您实际上是在滚动自己的RTTI)。
- 不要
重新思考为什么你首先需要这个。也许另一种方法会更好。也许是有回电或访客的东西。我不知道你在这里的目的,所以我真的不能说什么是合适的。
你能做一个基类并让所有其他类从基类继承吗。
您可以创建一个列表,其中包含基类元素的列表。现在这更多的是一个伪例子,但我希望这种方式能解决你的问题。示例:
class Base:
{
}
class whatever:Base
{
}
class whatever2:Base
int main()
{
list<whatever> object1;
list<whatever2> object2;
list<list<Base>> mainObj;
mainObj.push_back(object1);
mainObj.push_back(object2);
}
现在,如果问题只是在某个容器中具有不同于抽象数据类型的数据类型。难道你不能有一个单一的链接列表,并有你的节点通用。
示例:
template<typenameT>
struct Node
{
T data;
Node* next;
}
class LinkList
{
//Your code:
}
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- C++ 多态模板类,模板类型对象的实例化
- 如何分配适合容纳 T 类型对象的缓冲区(可能过度对齐、可能有运算符 new 等)
- 如何构造一个 std::variant 类型对象,其自身 Templated 和构造函数转发参数
- C++:初始化指向具有不同类型对象的指针数组
- 在类 C++ 中构造的模板类型对象
- 如何为同一类对象的成员函数保留单独的变量副本?
- 如何将颁发者名称设置为x509_req类型对象
- 将任何数据类型/对象作为参数传递以确定其大小
- 如何使用nullptr初始化同一类对象的静态指针数组?
- 将引用类型对象的数组从C#封送到C++
- <T> 从类型对象创建类型<T1>对象的构造函数
- RocksDB是存储同质对象的好选择吗
- C++是否有现有的方法来检查对象是否是派生类型对象
- C 模板:创建与现有对象相同的类型对象
- 链接列表中的虚函数 - 多种返回类型(对象)
- 没有适当操作员()的类型对象的呼叫
- 制作垫子类型对象的数组.输出窗口显示同一帧
- 抽象类型对象的分配
- 在std::list中就地创建自定义类型对象