2

I want to write my own Hash_function for an std::unordered_map instead of using the default one. I could find unordered_map::hash_function() on many websites. But using this i can only get the Hash value generated, using something like this :

/*Sample map of strings*/

unordered_map<string, string> sample;

// inserts key and elements
sample.insert({ "Tom", "MNNIT" });
sample.insert({ "Kate", "MNNIT" });

unordered_map<string, string>::hasher foo
    = sample.hash_function();

cout << foo("Tom") << endl;

But how can i have more control and create my own version of the hashing function ? So, that for example lets say for the key "Tom", i want hash value to be 100.

Evg
  • 25,259
  • 5
  • 41
  • 83
ssk
  • 96
  • 6
  • Use a good source code editor like [GNU emacs](https://www.gnu.org/software/emacs/) and read [this C++ reference](https://en.cppreference.com/w/cpp) and the documentation of your C++ compiler (e.g. [GCC](http://gcc.gnu.org/)) and debugger (e.g. [GDB](https://www.gnu.org/software/gdb/) – Basile Starynkevitch May 03 '21 at 19:23
  • Read wikipedia about [hash table](https://en.wikipedia.org/wiki/Hash_table), the [*Introduction to algorithms*](https://en.wikipedia.org/wiki/Introduction_to_Algorithms), and explain in several paragraphs of written English why do you require that the hashcode of `"Tom"` should be 100. Provide some [mre] in your question. What will happen to you if the hashcode of `"Tom"` is *not* 100? Read also [documentation of `std::unordered_map`](https://en.cppreference.com/w/cpp/container/unordered_map) – Basile Starynkevitch May 03 '21 at 19:25
  • 2
    This might be helpful https://stackoverflow.com/a/17017281/9676206 – Linux Geek May 03 '21 at 19:28

1 Answers1

7

std::unordered_map is templated off of a Hasher that defaults to std::hash<Key>. You can change your variable to std::unordered_map<string, string, CustomHasher>. unordered_map will then default construct a CustomHasher (it can also be passed in the constructor if you can't default construct your hashing object).

A custom hasher needs to provide a call operator such as the following:

struct CustomHasher
{
    // noexcept is recommended, but not required
    std::size_t operator()(const std::string& s) const /*noexcept*/
    {
        return /*hash computation here*/;
    }
};

Note: Writing code that depends on the hash values of something stored in an unordered_map is typically a bad design. There are valid use cases for wanting a custom hash function such as when you can exploit some information specific to your data to generate better hashes, but those cases are quite rare.

Dean Johnson
  • 1,682
  • 7
  • 12
  • 1
    Just a note: it doesn't have to be `noexcept`. – Evg May 03 '21 at 19:33
  • @Evg good point, removed it from the example. – Dean Johnson May 03 '21 at 19:34
  • 2
    I didn't mean to ask to remove `noexcept`. Having a `noexcept` hasher is a good thing but the standard doesn't mandate non-throwing custom hashers. For example, libstdc++ does some internal optimization for `noexcept` hashers (it a hasher is not `noexcept` then a hash code has to be stored in a node, see https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/hashtable.h#L44). In that particular implementation `noexcept` alone is not enough to trigger optimization (hasher should also be "fast"), but in some other implementation it might be important. – Evg May 03 '21 at 19:40