我想说,hasher
和key_equal
之间必然存在关系。如果两个元素相同(调用equal返回true),则它们必须具有相同的散列,否则将搜索错误的存储区元素。
但在http://www.cplusplus.com/reference/unordered_set/unordered_set/或http://en.cppreference.com/w/cpp/container/unordered_set
上没有写过这样的内容但它显然无法正常工作。 参见示例,当我尝试独立于元素的顺序(1,2 == 2,1)
过滤对#include <iostream>
#include <functional>
#include <unordered_set>
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);
}
namespace std
{
template<typename S, typename T>
struct hash<pair<S, T>>
{
inline size_t operator()(const pair<S, T> & v) const
{
size_t seed = 0;
::hash_combine(seed, v.first);
::hash_combine(seed, v.second);
return seed;
}
};
}
int main()
{
typedef std::pair<int, int> Pair;
Pair pa = std::make_pair(7,5);
Pair pb = std::make_pair(5,7);
Pair pc = std::make_pair(5,1);
Pair pd = std::make_pair(4,3);
Pair pe = std::make_pair(5,7);
struct PairEq
{
inline bool operator()(const Pair & p1, const Pair & p2) const
{
return (p1.first == p2.first && p1.second == p2.second)
|| (p1.first == p2.second && p1.second == p2.first);
}
};
std::unordered_set<Pair, std::hash<Pair>> h;
h.insert(pa);
h.insert(pb);
h.insert(pc);
h.insert(pd);
h.insert(pe);
for(auto & p : h)
{
std::cout << p.first << " " << p.second << "\n";
}
// note 5,7 AND 7,5 is outputted
}
假设通常的哈希属性是否安全 :如果两个元素相等,则它们具有相同的散列。两个相同的哈希值并不代表相同的元素?
答案 0 :(得分:4)
是的,这个关系是必需的,按照C ++标准,第23.2.5 / 5节[unord.req] - (无序关联容器,强调我的)
容器的Hash类型的对象 - 由hash表示 - 称为散列函数 容器。容器的Pred类型的对象 - 由pred表示 - 称为 容器的关键等式谓词。
如果容器的键等式谓词在传递这些值时返回true,则认为Key类型的两个值k1和k2是等效的。 如果k1和k2是等价的,则容器的散列函数应为返回相同的值。
请注意,此要求代表所有无序关联容器,而不仅仅是std::unordered_set
。