I want to have an std::unordered_map which uses arrays as keys. As long as a type has an operator== and an std::hash it can be used as a key.Here is my std::hash<std::array>template<class T, size_t N> struct std::hash<std::array<T, N>> {    auto operator() (const std::array<T, N>& key) const {        std::hash<T> hasher;        size_t result = 0;        for(size_t i = 0; i < N; ++i) {            result = result * 31 + hasher(key[i]); // ??        }        return result;    }};I copied the multiply by 31 from somewhere. An example here uses << and ^. I don't know which is better or how to apply the cppreference example to an array.// cppreference exampletemplate<> struct hash<S>    {        typedef S argument_type;        typedef std::size_t result_type;        result_type operator()(argument_type const& s) const        {            result_type const h1 ( std::hash<std::string>{}(s.first_name) );            result_type const h2 ( std::hash<std::string>{}(s.last_name) );            return h1 ^ (h2 << 1); // or use boost::hash_combine (see Discussion)        }    };It seems to work. All of the code compiles and the return values for std::hash<key_type> seem ok to me.using key_type = std::array<int, 2>;using hash_type = std::hash<key_type>;using map_type = std::unordered_map<key_type, int>;map_type map; // compileshash_type hasher; // compilesint main() {    // test return values of std::hash<key_type>    for(int y = -2; y < 3; ++y) {        for(int x = -2; x < 3; ++x) {            std::cout << hasher({x, y}) <<  ;        }        std::cout << std::endl;    }}The values printed from this code are:18446744073709551552 18446744073709551583 18446744073709551614 29 60 18446744073709551553 18446744073709551584 18446744073709551615 30 61 18446744073709551554 18446744073709551585 0 31 62 18446744073709551555 18446744073709551586 1 32 63 18446744073709551556 18446744073709551587 2 33 64I'm not sure what makes a good hash function for std::unordered_map, so I'd appreciate any feedback on how to make this hash function better.
Specializing std::hash for std::array
c++;array;hash map
Implicit assumption:It looks like you make an implicit assumption here:std::hash<T> hasher;making it non-member means that you assume std::hash is not allowed to have any state, which is false. It is not required to be monostate, so the hasher should be a member of the specialization.When the assumption can bite you?Consider this implementation in pseudocode:store `std::map<T, counter_type>` as data member.on every call to hash an array, for each element:    result = result * 31 + map[elem]Imagine that counter_type is just a counter, e.g. each unique instance gives a unique number, in incremental order. If you would leave the std::hash<T> as local, this would happen:on every call to hash an array for each element:    result = result * 31 + 0 //or whatever counter starts fromSo it would degrade any unordered container.Example versionExample version uses specific operators to the specific class, whereas your code is generic. So, I guess your version should be fine with the applied change described above.31I've seen it being used in Effective Java by Joshua Bloch. I believe he described it as prime which is closest to the power of two, which has positive impact on overflow (e.g. one number won't be repeated for pretty long time). I don't have any maths to back this up, but I believe the direction is right.