Search code examples
c++11hashunordered-set

unordered_set hash for type, whose comparison uses part of the type data


I need std::unordered_set of pairs, whose first elements should be different.

Is it correct to hash only first element of pairs, as below?

using Pair = std::pair<int, int>;

struct Eq
{
    bool operator() ( Pair const& lhs,
                      Pair const& rhs ) const
    {
        return (lhs.first == rhs.first);
    }
};

struct Hash
{
    std::size_t operator() ( Pair const &p ) const
    {
        return std::hash<int>()( p.first );
    }
};

// No two pairs with same '.first'.
std::unordered_set<Pair, Hash, Eq> pairs;

for ( Pair const& p : ... )
{
    pairs.insert(p);
}

In general, for unordered_set<T>:

If equality functor for type T does not use part (some data members) of T, it makes sense not to use that part in hash<T> either.

Is this right?


Solution

  • Yeap, should work fine. From the documentation to std::unordered_set::insert() (emphasis mine):

    Inserts element(s) into the container, if the container doesn't already contain an element with an equivalent key.

    You clearly provided a predicate that says elements should be treated equivalent when their first fields match. And you specified a hash that makes sure equivalent elements end up in the same bucket. So this looks good to me.