2017-02-18 63 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

相關問題