Specializing std::hash for std::array 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&lt;std::array&gt;

template&lt;class T, size_t N&gt; 
struct std::hash&lt;std::array&lt;T, N&gt;&gt; {
    auto operator() (const std::array&lt;T, N&gt;&amp; key) const {
        std::hash&lt;T&gt; hasher;
        size_t result = 0;
        for(size_t i = 0; i &lt; N; ++i) {
            result = result * 31 + hasher(key[i]); // ??
        }
        return result;
    }
};


I copied the multiply by 31 from somewhere. An example here uses &lt;&lt; and ^. I don't know which is better or how to apply the cppreference example to an array.

// cppreference example
template&lt;&gt; struct hash&lt;S&gt;
    {
        typedef S argument_type;
        typedef std::size_t result_type;
        result_type operator()(argument_type const&amp; s) const
        {
            result_type const h1 ( std::hash&lt;std::string&gt;{}(s.first_name) );
            result_type const h2 ( std::hash&lt;std::string&gt;{}(s.last_name) );
            return h1 ^ (h2 &lt;&lt; 1); // or use boost::hash_combine (see Discussion)
        }
    };


It seems to work. All of the code compiles and the return values for std::hash&lt;key_type&gt; seem ok to me.

using key_type = std::array&lt;int, 2&gt;;
using hash_type = std::hash&lt;key_type&gt;;
using map_type = std::unordered_map&lt;key_type, int&gt;;

map_type map; // compiles
hash_type hasher; // compiles

int main() {
    // test return values of std::hash&lt;key_type&gt;
    for(int y = -2; y &lt; 3; ++y) {
        for(int x = -2; x &lt; 3; ++x) {
            std::cout &lt;&lt; hasher({x, y}) &lt;&lt; " ";
        }
        std::cout &lt;&lt; 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 64


I'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.
What is a "good" hash function?

The requirement of a hash function is that it always produces the same value for a given key (in the same instance of the program) and a good hash function should produce each output with equal probability.

Your function achieves this (multiplying by a prime such as 31 is a well-known way of combining hash values to reduce collisions caused by different permutations of the same values).

However, it's up to you to decide whether the hash inputs in your application have a random distribution, or whether they have some pattern that may perturb the output distribution from the hash function.

Can you use your mental reasoning to force a collision?  {1, 0} and {0, 31} might do it, for example.  Can you think of any reason why your code might produce collisions more often than by independent chance?

Style points

The code is neat and clear.  It might be an idea to allow an alternative to std::hash&lt;T&gt; to be supplied by the caller, just as std::unordered_map itself allows a user-supplied hasher.  This may be useful with char* strings, for example.

You could simplify the loop, as std::array supports range-based for:

    for (const auto&amp; element: key) {
        result = result * 31 + hasher(element);
    }


More tests

It's good that you've provided a test suite.  Consider whether you could add more tests - at least one test with an element type other than int and at least least one with different array lengths (you should probably include a test for std::array&lt;char, 1&gt; as a boundary case, for example).

Alternatives

Boost provides a hash() function that accepts built-in (i.e. C-style) arrays, so you might be able to reinterpret_cast the std::array.  I've never tried this, but I don't see why it wouldn't work...