如何在C ++中获取运行时给定元素的模板类型?

时间:2012-07-06 22:14:04

标签: c++ templates polymorphism

我正在设计一个简单的Array类,它具有保存任何类型对象的能力,就像一个可以在一个对象中保存多种类型数据的向量。 (这是出于学习目的。)

我有一个名为Container的空基类:

class Container {};

一个名为Object的模板化子类:

template <class T>
class Object : public Container {
    T& object;
public:
    Object(T& obj = nullptr) : object(obj) {}
};

我有一个Array类,其中包含vector指向Container的指针,用于保存Object s:

class Array {
    std::vector<Container *> vec;
public:
    template <class T>
    void add_element(const T&);
    auto get_element(int);
};

add_element将元素存储到Object中并将其放入vec

template <class T>
void Array::add_element(const T& element)
{
    vec.push_back(new Object<T>(element));
}

get_elementObject中移除元素并将其传递回调用者。这就是我的问题所在。要从Object中删除元素,我需要知道它是Object的类型:

auto Array::get_element(int i)
{
    return (Object</* ??? */> *)vec[i])->object;
}

我有什么方法可以找出我正在存储的对象吗?

编辑:因为人们声称这是不可能的,所以这个怎么样。有没有办法在类中存储类型信息? (我知道你可以用红宝石做到这一点)。如果我能做到这一点,我可以在每个get_element中存储Object的返回类型。

3 个答案:

答案 0 :(得分:2)

我正在考虑为您的get_element创建此模板的内容。

template <class T>
T& Array::get_element(int i, T &t)
{
    Object<T> *o = dynamic_cast<Object<T> *>(vec[i]);
    if (o == 0) throw std::invalid_argument;
    return t = o->object;
}

Array arr;
double f;
int c;

arr.get_element(0, f);
arr.get_element(1, c);

但另外,你可以使用它:

template <class T>
T& Array::get_element(int i)
{
    Object<T> *o = dynamic_cast<Object<T> *>(vec[i]);
    if (o == 0) throw std::invalid_argument;
    return o->object;
}

f = arr.get_element<double>(0);
c = arr.get_element<int>(1);

答案 1 :(得分:1)

必须在编译时确定像Array::get_element这样的函数的返回类型。由于类Array不知道它在编译时存储的容器类型,唯一的选择是只返回基本Container*指针。然后,该代码的用户可以使用虚函数和/或dynamic_cast来处理这些通用容器。

答案 2 :(得分:1)

dynamic_cast&lt;&gt;(),当在指针上使用时,可用于检查强制转换是否实际可行,因为当类型不匹配时它返回NULL。

但是,您可能想重新考虑您的设置;如果你可以避免使用dynamic_cast,那么你可以使用dynamic_cast,并且如果object-is-type1那么执行此操作;否则如果object-is-type2则执行此操作;否则如果object-is-type3 ......“几乎总是设计糟糕的明显标志。

在你的get_element中使用auto可能是解决问题的一个技巧,你不知道它将是什么类型 - 但这不起作用。编译器仍然必须知道返回类型;它不能在运行时改变。

编辑:您可能还会退后一步,问自己是否真的需要一个可以存储“任何东西”的数组。我已经使用了Objective-C很长一段时间了,它基本上围绕着这样的想法:一切都只是一个“对象”,人们可以在任何事情上调用任何东西,它们都在运行时整理出来。但是,我发现实际使用这种情况很少见......特别是对于容器,我发现我使用的每个NSArray只有一种类型的对象,或者可能是一个共同的基类,但实际上并不是不同的,不相关的类