I just found myself a little bit surprised being unable to simply use a
std::unordered_set<std::array<int, 16> > test;
because there does not seem to be a std::hash
specialization for std::array
s. Why is that? Or did I simply not find it? If there is indeed none, can the following implementation attempt be simplified?
namespace std
{
template<typename T, size_t N>
struct hash<array<T, N> >
{
typedef array<T, N> argument_type;
typedef size_t result_type;
result_type operator()(const argument_type& a) const
{
hash<T> hasher;
result_type h = 0;
for (result_type i = 0; i < N; ++i)
{
h = h * 31 + hasher(a[i]);
}
return h;
}
};
}
I really feel this should somehow be part of the standard library.
std::string
and friends have that privilege. Would I be really unpopular if I said that it's because C++'s effort to drag itself towards the current state of the art in terms of standard data structures has not yet done the whole job? Actually, there aren't any requiredhash
specializations for templates (and which would in turn require their template arguments to be hashable). The only required specializations are for built-in type and four concrete string classes. So I suspect that a line was drawn there. – Petrozavodskstring
,u16string
,u32string
,wstring
(21.6 in C++11). I'd say thatpair
andtuple
should be the next-highest-priority targets, followed by standard containers, followed by a default hash for any aggregate type composed of hashable members. – Petrozavodskstring
hasher requires an internal function for hashing a block of memory. I wonder why they did not require implementations to expose it directly? – Krakenhash
function of its own, presumably so that you can collapse different characters together in a locale-dependent manner to keephash
consistent with comparisons. So it is exposed, but I don't know whether or not the specializations ofstd::hash
for string types are supposed to use it, I'm not properly familiar with this stuff. – Petrozavodskboost::hash_combine
, were I to implement hashing on collection. – Pirozzoboost::hash_combine
usesseed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
if anyone is curious. That looks a bit more robust. – Chuff