2011-06-07 64 views
1

問題是:我想使用unordered_map存儲鍵和值,其中鍵可以是A類或B類,具體取決於用戶選項。這兩個類A和B繼承來自同一類P.unordered_map和虛擬模板

class A: public P {...} 
class B: public P {...} 

我想與抽象P艙定義地圖和以後,根據運行時間選項,其中A或B,爲分配有一個地圖關鍵:

unordered_map< P, CValue, P::hash, P::equal_to> * pmap = new unordered_map< A, CValue, A::hash, A::equal_to>; 

,但我會得到錯誤:

cannot convert ... in initialization 

我如何聲明這樣一個 「虛擬」 的地圖?

+3

所以我們map_unordered,unordered_map和unsorted_map - 它要價太高了,你得到一個簡單的名字吧? – 2011-06-07 10:35:40

+0

你能舉一個例子說明如何使用它?另外,您是否需要具有異構密鑰的地圖,還是您需要一組具有同類密鑰的地圖? – 2011-06-07 13:29:31

+0

在代碼的開始部分,我選擇使用哪種類型的鍵:A或B,它將在程序後面的所有時間使用。但是我不能「靜態」定義地圖模板,因爲關鍵類型取決於用戶的選項。在這種特殊情況下,我將用它來統計一些網絡統計信息,並且我想通過AS號碼的前綴_或_來聚合它們。 – 2011-06-07 15:51:05

回答

3

這裏有一個例子,你如何可以使鍵控上P*地圖,還是在派生類中使用不同的實現:

struct P 
{ 
    virtual size_t hash_self() const = 0; 
    virtual bool equal(const P &) const = 0; 
}; 

struct A : public P 
{ 
    inline bool operator==(const A & other) const { return false; /*Implement!*/} 
    size_t hash_self() const { return 1; /*Implement!*/ } 
    bool equal(const P & p) const { return *this == dynamic_cast<const A &>(p); } 
}; 

struct PHash 
{ 
    size_t operator()(const P * const p) const { return p->hash_self(); } 
}; 

struct PEqual 
{ 
    bool operator()(const P * const p, const P * const q) const { return p->equal(*q); } 
}; 


#include <unordered_map> 

std::unordered_map<P *, double, PHash, PEqual> pmap{{ new A, .5 }}; 

的動態轉換是有效的,因爲你答應只比較相同的派生類型的指針。

如果你想更清潔,你很可能專門std::hash<P*>std::equal_to<P*>

namespace std 
{ 
    template<> struct hash<P*> 
    { size_t operator()(P * const & p) const { return p->hash_self(); } }; 

    template<> struct equal_to<P*> : public binary_function<P*, P*, bool> 
    { bool operator()(P * const & p, P * const & q) const { return p->equal(*q); } }; 
} 

std::unordered_map<P *, int> qmap{{new A, -11}}; // just works! 
2
unsorted_map< P, CValue, P::hash, P::equal_to> * pmap = new unsorted_map< A, CValue, A::hash, A::equal_to>; 

P型與A型不相同。

所以X<P>是與X<A>不同的類型。這意味着,該代碼

X<P> *pX = new X<A>(); 

不會進行編譯,即使AP的。 GCC會給這個錯誤(ideone):

error: cannot convert ‘X<A>*’ to ‘X<P>*’ in initialization 

如果你知道X<A>是一個完全不同的類型X<P>這是不言自明。

請注意,它的AP派生。但X<A>仍不是從X<P>派生。我認爲你把前者和後者搞混了。

因此,我認爲你需要的是這樣的:

unorder_map<P*, P::hash, P::equal_to> objectMap; 

您可以插入A*類型的對象插入此地圖:

objectMap.insert(new A()); 

可以插入B*類型也是對象:

objectMap.insert(new B()); 

畢竟,你想要多態地處理地圖中的所有對象。

+0

謝謝,看起來很有希望。如果我對A和B有不同的散列函數,我應該如何應用它們?一旦我聲明objectMap,並且我知道是否應該使用A或B,我可以做一些像objectMap :: hash = A :: hash嗎? – 2011-06-07 10:55:41