2017-02-18 65 views
0

我想创建一个模板化API来访问存储在向量向量中的派生类型。外部向量对每个派生类型都有一个元素。内部向量具有这些类型的集合。为存储在向量中的派生类对象创建模板API

std::vector<std::vector<MyBaseClass>* > items; 

理想情况下,我想提供一个API,其中可以添加和访问派生类型的MyBaseClass(没有专门的模板)。事情是这样的:

T& addItem(size_t index, T& item); 
T& getItem(size_t index); 

使用这样的:

AClass : public MyBaseClass {}; 
BClass : public MyBaseClass {}; 

addItem<AClass&>(123, item); 
addItem<BClass&>(456, item); 

AClass& = getItem<AClass&>(123); 
BClass& = getItem<BClass&>(456); 

的原因缺乏专门的模板,是我想能够使用新的派生类型,而不必修改这个代码的其他开发人员。

那么,有没有一种方法可以实现这种类型的API,而无需知道派生类的类型并专门化代码?

是否可以使用联合和模板来做到这一点?

注意:内部向量需要将其数据连续存储在内存中,所以我没有使用指针。

注意:我在不使用Boost的情况下使用C++ 11。

谢谢。

+4

'std :: vector '不能包含派生类型的对象。期。 – aschepler

+4

将对象添加到'vector '时,向量将只存储对象的基类部分。请参见[什么是对象切片?](http://stackoverflow.com/questions/274626/what-is-object-slicing) –

+0

您可以使用'std :: vector >',然后只需要'addItem'在指针上执行一次转换并返回一个引用。当然,如果转换为错误的类型并返回无效的引用,这当然会是未定义的行为。 – Cornstalks

回答

0

沿着也许这些东西线:

class FancyStore { 
public: 
    template <typename T> 
    T& addItem(const T& item) { 
    void*& raw = store_[typeid(T)]; 
    if (!raw) { 
     raw = new std::vector<T>(); 
    } 
    auto v = static_cast<std::vector<T>*>(raw); 
    v->push_back(item); 
    return v->back(); 
    }  

    template <typename T> 
    T& getItem(size_t index) { 
    void* raw = store_[typeid(T)]; 
    auto v = static_cast<std::vector<T>*>(raw); 
    return (*v)[index]; 
    } 

private: 
    std::unordered_map<std::type_index, void*> store_; 
}; 

Live demo。复制,析构函数,错误处理作为读者的练习。

+0

非常感谢。这看起来像我所需要的。 – user1824607

+0

有没有办法通过单个函数调用来调整所有向量的大小,即使我直到运行时才知道类型? 例如void resizeItemStore(size_t size); – user1824607

+0

我可以遍历store_并使用decltype调用模板化的调整大小函数吗? – user1824607