Como faço para combinar valores de hash em C ++ 0x?

C ++ 0x adiciona hash(...) .

Eu não consegui encontrar uma function hash_combine, como apresentado no boost . Qual é a maneira mais limpa de implementar algo assim? Talvez, usando C ++ 0x xor_combine ?

Bem, apenas faça como os caras do impulso fizeram:

 template  inline void hash_combine(std::size_t& seed, const T& v) { std::hash hasher; seed ^= hasher(v) + 0x9e3779b9 + (seed< <6) + (seed>>2); } 

Compartilharei aqui, pois pode ser útil para outras pessoas que estejam procurando por essa solução: a partir da resposta do @KarlvonMoor , aqui está uma versão de modelo variável, que é mais usada se você tiver que combinar vários valores:

 inline void hash_combine(std::size_t& seed) { } template  inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { std::hash hasher; seed ^= hasher(v) + 0x9e3779b9 + (seed< <6) + (seed>>2); hash_combine(seed, rest...); } 

Uso:

 std::size_t h=0; hash_combine(h, obj1, obj2, obj3); 

Isso foi escrito originalmente para implementar uma macro variádica para tornar facilmente os tipos personalizados hashable (que eu acho que é um dos principais usos de uma function hash_combine ):

 #define MAKE_HASHABLE(type, ...) \ namespace std {\ template<> struct hash {\ std::size_t operator()(const type &t) const {\ std::size_t ret = 0;\ hash_combine(ret, __VA_ARGS__);\ return ret;\ }\ };\ } 

Uso:

 struct SomeHashKey { std::string key1; std::string key2; bool key3; }; MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3) // now you can use SomeHashKey as key of an std::unordered_map 

Isso também poderia ser resolvido usando um modelo variadic da seguinte maneira:

 #include  template  struct hash; template struct hash : public std::hash { using std::hash::hash; }; template  struct hash { inline std::size_t operator()(const T& v, const Rest&... rest) { std::size_t seed = hash{}(rest...); seed ^= hash{}(v) + 0x9e3779b9 + (seed < < 6) + (seed >> 2); return seed; } }; 

Uso:

 #include  int main(int,char**) { hash hasher; std::size_t h = hasher(1, 0.2f, 2.0, "Hello World!"); } 

Pode-se certamente fazer uma function de modelo, mas isso pode causar alguma dedução do tipo desagradável, por exemplo, o hash("Hallo World!") Calculará um valor de hash no ponteiro em vez de na cadeia de caracteres. Esta é provavelmente a razão, porque o padrão usa uma estrutura.