2011-06-07 87 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