¿Cómo combino valores hash en C ++ 0x?

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

Sin embargo, no pude encontrar una función hash_combine, como se presenta en boost . ¿Cuál es la forma más limpia de implementar algo como esto? Quizás, usando C ++ 0x xor_combine ?

Bueno, hazlo como lo hicieron los chicos:

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

Lo compartiré aquí ya que puede ser útil para otros que buscan esta solución: a partir de la respuesta de @KarlvonMoor , aquí hay una versión de plantilla variadica, que es más estricta en su uso si tiene que combinar varios 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); 

Esto fue escrito originalmente para implementar una macro variadica para hacer fácilmente hashable los tipos personalizados (que creo que es uno de los usos principales de una función 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 

Esto también podría resolverse usando una plantilla variadica de la siguiente manera:

 #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!"); } 

Uno ciertamente podría hacer una función de plantilla, pero esto podría causar una deducción de tipo desagradable, ej. hash("Hallo World!") Calculará un valor hash en el puntero en lugar de en la cadena. Esta es probablemente la razón por la cual el estándar usa una estructura.