C++ 0x dodaje hash<...>(...)
.Jak połączyć wartości mieszania w C++ 0x?
Nie mogłem znaleźć funkcji hash_combine, jak przedstawiono w boost. Jaki jest najczystszy sposób wdrożenia czegoś takiego? Być może używając C++ 0x xor_combine
?
C++ 0x dodaje hash<...>(...)
.Jak połączyć wartości mieszania w C++ 0x?
Nie mogłem znaleźć funkcji hash_combine, jak przedstawiono w boost. Jaki jest najczystszy sposób wdrożenia czegoś takiego? Być może używając C++ 0x xor_combine
?
Cóż, po prostu zrób to jak faceci przypominającego to zrobił:
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);
}
Tak, to jest najlepsze, co mogę zrobić. Nie rozumiem, jak komitet normalizacyjny odrzucił coś tak oczywistego. –
@Neil: Zgadzam się. Myślę, że prostym rozwiązaniem dla nich będzie wymóg posiadania przez bibliotekę skrótu dla 'std :: pair' (lub' tuple', even). Obliczałoby to mieszanie każdego elementu, a następnie je łączy. (I w duchu standardowej biblioteki, w sposób określony w implementacji). – GManNickG
Istnieje wiele oczywistych rzeczy pominiętych w standardzie. Proces intensywnej wzajemnej oceny sprawia, że trudno jest oderwać te małe rzeczy od drzwi. – stinky472
będę go tutaj podzielić, ponieważ może to być przydatne dla innych szukających tego rozwiązania: począwszy od @KarlvonMoor odpowiedź, oto o zmiennej liczbie argumentów wersja szablonu, który jest terser w jego użytkowania, jeśli trzeba połączyć ze sobą kilka wartości:
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...);
}
Zastosowanie:
std::size_t h=0;
hash_combine(h, obj1, obj2, obj3);
ten został napisany pierwotnie wdrożyć zmiennej liczbie argumentów makra łatwo typy niestandardowe hashable (co moim zdaniem jest jednym z podstawowych zastosowań o hash_combine
funkcji):
#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;\
}\
};\
}
Zastosowanie:
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
Możliwy duplikat [Jak specjalizować std :: hash dla typów zdefiniowanych przez użytkownika?] (Https://stackoverflow.com/questions/24361884/how-to-specialize-stdhasht-for-user-defined- typeses) –
Raedwald
Specjalizacja 'std :: hash' z natury musi łączyć sub h popioły członków danych. Wszystkie zastosowane tam dowody i rozumowanie mają zastosowanie do funkcji "hash_combine". – Raedwald
@Raedwald Widzę teraz, że było to jedno z jego pytań, ale żeby być uczciwym, jego pytanie jest perypetialne i pośrednie. Dodaj tutaj swoją odpowiedź, jeśli masz coś do dodania. –