如何将unordered_set与自定义类型一起使用?

时间:2012-03-15 22:52:14

标签: c++ visual-c++

是否需要为自定义类型创建自己的哈希函数?我可以使用unordered_set吗?

2 个答案:

答案 0 :(得分:14)

标准库包含std::hash<T>的基本类型,指针和std::string(或更确切地说,std::basic_string的所有特化)的特化。

不幸的是,库包含以下重要的新旧组合函数,但它是Boost的一部分,您应将其复制到代码中:

template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

使用此函数,您可以散列对,元组,数组以及任何类型的范围自身可以清除的元素。浏览Boost源代码,了解许多示例和有用的实现。显然,您可以使用此函数为您自己的类型创建哈希函数。例如,这里是一对哈希:

template<typename S, typename T> struct pair_hash<std::pair<S, T>>
{
    inline std::size_t operator()(const std::pair<S, T> & v) const
    {
         std::size_t seed = 0;
         hash_combine(seed, v.first);
         hash_combine(seed, v.second);
         return seed;
    }
};

请注意,哈希组合不会产生良好的哈希值。结果具有非常差的统计质量(例如,创建散列冲突非常容易)。好的散列需要能够看到所有原始输入位,并且不能通过部分散列来计算。 (这就是为什么目前的标准库没有更好的解决方案;没有人能够提出令人满意的设计。)

答案 1 :(得分:9)

是的,您需要编写自己的哈希函数。这听起来并不像听起来那么糟糕:如果你的班级有任何你认为合适的可清除成员,你就可以返回该成员的哈希值。

您可以通过专门化std::hash或通过显式传递哈希类作为模板参数来提供此哈希。

相关问题