C++ 0x agrega hash<...>(...)
.¿Cómo combino valores hash en C++ 0x?
No he podido 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
?
C++ 0x agrega hash<...>(...)
.¿Cómo combino valores hash en C++ 0x?
No he podido 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, sólo lo hacen como los chicos a impulsar lo hizo:
template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
sí, eso es lo mejor que podría hacer también. No entiendo cómo el comité de normas rechazó algo tan obvio. –
@Neil: Estoy de acuerdo. Creo que una solución simple para ellos sería el requisito de que la biblioteca tenga un hash para 'std :: pair' (o' tuple', incluso). Calcularía el hash de cada elemento, luego los combinaría. (Y en el espíritu de la biblioteca estándar, en una implementación definida). – GManNickG
Hay muchas cosas obvias omitidas en el estándar. El proceso de revisión intensiva por pares hace que sea difícil sacar esas pequeñas cosas de la puerta. – stinky472
lo voy a compartir aquí, ya que puede ser útil para otros que buscan esta solución: a partir de @KarlvonMoor respuesta, aquí está una versión de la plantilla variadic, que es más concisa en su uso si usted tiene que combinar varios valores juntos:
inline void hash_combine(std::size_t& seed) { }
template <typename T, typename... Rest>
inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
std::hash<T> 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 variadic para hacer fácilmente tipos personalizados hashable (que creo que es uno de los usos principales de una función hash_combine
):
#define MAKE_HASHABLE(type, ...) \
namespace std {\
template<> struct hash<type> {\
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
Posible duplicado de [¿Cómo especializar std :: hash para tipos definidos por el usuario?] (Https://stackoverflow.com/questions/24361884/how-to-specialize-stdhasht-for-user-defined-types) –
Raedwald
Una especialización de 'std :: hash' tiene que combinar inherentemente el sub h cenizas de los miembros de datos. Toda la evidencia y el razonamiento aplicados allí se aplican a una función 'hash_combine'. – Raedwald
@Raedwald Veo ahora que esa fue una de sus preguntas, pero para ser justos, su pregunta es perifrástica e indirecta. Agregue su respuesta aquí si tiene algo que agregar. –