2016-03-14 53 views
1

我想创建一个可重用的IdHash和IdEqualTo类,它接受常量实例(引用,原始指针或智能指针),并返回散列值或比较结果。自定义散列,与指针和引用一起工作

template<class Entity, class Id> 
struct IdFunc { 
    typedef typename std::function<const Id& (const Entity&)> type; 
}; 

template<class Entity, class Id> 
struct IdHash { 
public:  
    explicit IdHash(const typename IdFunc<Entity, Id>::type& idFunc) : idFunc_(idFunc) {} 
    std::size_t operator()(const Entity& o) const { 
     return std::hash<Id>()(idFunc_(o)); 
    } 
private: 
    typename IdFunc<Entity, Id>::type idFunc_;  
}; 
// IdEqualTo follows the same pattern 

我的第一次尝试使用unordered_set<MyClass, IdHash<string, MyClass>, IdEqualTo<...>>。由于MyClass将是继承层次结构而不是单一类型,因此我需要切换到指针:unordered_set<unique_ptr<MyClass>, IdHash<string, MyClass>, ...>。现在我需要一个需要unique_ptr &的操作符版本。我提供了以下

std::size_t operator()(const Entity* o) const { 
     return std::hash<Id>()(idFunc_(*o)); 
    } 

希望unique_ptr<MyClass>&能以某种方式转化为MyClass*。它没有工作。由于此实用程序应该超越存储类型,因此如何使它可以与引用,原始指针或智能指针一起工作?

请参阅code sample

谢谢。

+1

添加一个重载'std :: size_t operator()(const std :: unique_ptr &o)const'? – immibis

+0

@immibis如果我下一次需要使用像shared_ptr 或E *这样的其他指针类型,那么该怎么办? –

回答

0

从智能指针到原始指针没有自动转换(尽管您可以使用get())。

为智能指针专门化您的模板,这是它在标准库和增强中完成的方式。

template <class Inner, class Id> 
struct IdHash<std::unique_ptr<Inner>, Id> { 
    typedef std::unique_ptr<Inner> PtrType; 
    std::size_t operator() (const PtrType &pointer) const { 
     return std::hash<Id>()(idFunc_(pointer.get()); 
    } 
}; 

您可能还需要创建每次调用operator()时间std::hash<Id>情况只有一次,而不是。