2010-04-07 13 views
61

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?

+0

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

+0

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

+0

@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. –

Odpowiedz

63

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); 
} 
+15

Tak, to jest najlepsze, co mogę zrobić. Nie rozumiem, jak komitet normalizacyjny odrzucił coś tak oczywistego. –

+8

@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

+3

Istnieje wiele oczywistych rzeczy pominiętych w standardzie. Proces intensywnej wzajemnej oceny sprawia, że ​​trudno jest oderwać te małe rzeczy od drzwi. – stinky472

20

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 
Powiązane problemy