0

I have a std::unordered_map with keys of type std::pair<T*, T*> (i.e., a pair of pointers).

The code base has the following hash functor defined:

struct pair_hash {
  template<typename T>
  std::size_t operator()(std::pair<T, T> const &p) {
    return (std::hash<T>()(p.first) + 0x9e3779b9) ^ (std::hash<T>()(p.second) + 0x9e3779b9);
  }
};

And is used as:

std::unordered_map<std::pair<T*, T*>, U, pair_hash> myDictionary;

where U is an arbitrary object.

Now the hash functor displayed above must have certain issues because in VC++ it gives me an out of bounds crash in std::unordered_map::find.

Q:

  • Could it be that my hash functor is problematic or this behaviour is attributed to VC++ itself?
  • Is there a "proper/more proper" way to hash a pair of pointers?
101010
  • 41,839
  • 11
  • 94
  • 168

2 Answers2

2
return (std::hash<T>()(p.first) + 0x9e3779b9) ^ (std::hash<T>()(p.first) + 0x9e3779b9);
//                                                                ^^^^^
//                                                              p.second!
//                                                                         ^^^^^^^^^^
// Choose different magic constant to prevent collisions between (p1, p2) and (p2, p1)

Your function was returning zero for every pair of pointers. Therefore you were getting lots of collisions in the unordered_map.

michalsrb
  • 4,703
  • 1
  • 18
  • 35
2

If you can use Boost, there's a very useful hash_combine function that you could use.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135