问题
I want to be able to use a std::pair
as a key in an unordered_container. I know that I could do this the following way:
template<typename T>
void
hash_combine(std::size_t &seed, T const &key) {
std::hash<T> hasher;
seed ^= hasher(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
namespace std {
template<typename T1, typename T2>
struct hash<std::pair<T1, T2>> {
std::size_t operator()(std::pair<T1, T2> const &p) const {
std::size_t seed(0);
::hash_combine(seed, p.first);
::hash_combine(seed, p.second);
return seed;
}
};
}
However, I want the hashing to ignore the order of the elements in the std::pair
(i.e., to return the same seed for std::pair<A, B>
and std::pair<B, A>)
.
One way I thought to achieve this is to apply some kind of ordering when creating my std::pair<A, B>
(i.e., some kind of custom std::make_pair
).
But this is too restrictive since objects A, B
might not have an order.
Q:
Is there a standard way to hash a std::pair
, such that the order of elements is ignored and the same seed is returned either for std::pair<A, B>
and std::pair<B, A>
?
回答1:
Don't order the pairs, order the hashes:
namespace std {
template<typename T1, typename T2>
struct hash<std::pair<T1, T2>> {
std::size_t operator()(std::pair<T1, T2> const &p) const {
std::size_t seed1(0);
::hash_combine(seed1, p.first);
::hash_combine(seed1, p.second);
std::size_t seed2(0);
::hash_combine(seed2, p.second);
::hash_combine(seed2, p.first);
return std::min(seed1, seed2);
}
};
}
[Live example]
来源:https://stackoverflow.com/questions/28367913/how-to-stdhash-an-unordered-stdpair