Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

unordered_map with self-defined hash function cannot work

I want to use type shared_ptr as the key of an unordered_map. In order to use the content of the string as key rather than use the pointer address, I define function "hashFn" as hash function. However, code below cannot work. I insert (p1, 0) and then find p2 which has the same content with p1 in the map, but failed. The code print "0".

#include <iostream>
#include <memory>
#include <unordered_map>
using namespace std;

int main() {
  auto hashFn = [](const shared_ptr<string> &p) -> size_t {
    cout << hash<string>()(*p) << endl;
    return hash<string>()(*p);
  };
  auto map =
      unordered_map<shared_ptr<string>, int, decltype(hashFn)>(0, hashFn);
  auto p1 = shared_ptr<string>(new string("abc"));
  auto p2 = shared_ptr<string>(new string("abc"));
  auto [_it, flag] = map.emplace(p1, 0);
  cout << flag << endl;
  int c = map.count(p2);
  cout << c << endl;
  return 0;
}

I print the hash result in my hashFn and it shows the result of p1 and p2 is the same. It is confusing…

  auto hashFn = [](const shared_ptr<string> &p) -> size_t {
    cout << hash<string>()(*p) << endl;
    return hash<string>()(*p);
  };

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

p1 and p2 are different pointers, so it is natural that p1 isn’t found when searching for p2.

Different values can have same hash, so equality of hash doesn’t mean equality of values.

If you want to override how to check if keys are equal, you should specify the equal argument in the constructor of std::unordered_map.

#include <iostream>
#include <memory>
#include <unordered_map>
using namespace std;

int main() {
  auto hashFn = [](const shared_ptr<string> &p) -> size_t {
    cout << hash<string>()(*p) << endl;
    return hash<string>()(*p);
  };
  auto equalFn = [](const shared_ptr<string> &lhs, const shared_ptr<string> &rhs) -> bool {
    return *lhs == *rhs;
  };
  auto map =
      unordered_map<shared_ptr<string>, int, decltype(hashFn), decltype(equalFn)>(0, hashFn, equalFn);
  auto p1 = shared_ptr<string>(new string("abc"));
  auto p2 = shared_ptr<string>(new string("abc"));
  auto [_it, flag] = map.emplace(p1, 0);
  cout << flag << endl;
  int c = map.count(p2);
  cout << c << endl;
  return 0;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading