Im Bereich der C-Standardbibliotheken das Konzept von Tupeln und ihre Verwendung als Schlüssel in ungeordneten Sammlungen wie std::unordered_map und std::unordered_set können eine Herausforderung darstellen. Standardmäßig ist für Tupel keine generische Hash-Funktion definiert, sodass Entwickler die mühsame Aufgabe haben, eine solche manuell zu definieren.
Das Definieren einer benutzerdefinierten Hash-Funktion für Tupel kann umständlich und fehleranfällig sein. Um dieses Problem anzugehen, suchen Entwickler häufig nach einer allgemeineren Lösung, die den Prozess automatisiert.
Während der Standard nicht explizit eine generische Hash-Funktion für Tupel bereitstellt, ist dies ein Standard -konformer Ansatz ist verfügbar. Durch das Verschieben des Codes in einen benutzerdefinierten Namespace ist es möglich, undefiniertes Verhalten zu vermeiden, das mit der Spezialisierung auf den std-Namespace verbunden ist.
Bei diesem Ansatz wird ein benutzerdefinierter Namespace, hash_tuple, mit seiner eigenen Implementierung der Hash-Funktion erstellt . Diese Implementierung sendet Nicht-Tupel-Typen an die Funktion std::hash.
namespace hash_tuple{ template <typename TT> struct hash { size_t operator()(TT const& tt) const { return std::hash<TT>()(tt); } }; }
Der rekursive Vorlagencode wird geändert, um hash_tuple::hash anstelle von std::hash:
namespace hash_tuple{ namespace { template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= hash_tuple::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } } }
namespace hash_tuple{ template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...> >::apply(seed, tt); return seed; } }; }
unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
namespace std{ namespace { // Code from boost // Reciprocal of the golden ratio helps spread entropy // and handles duplicates. // See Mike Seymour in magic-numbers-in-boosthash-combine: // http://stackoverflow.com/questions/4948780 template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } // Recursive template code derived from Matthieu M. template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1> struct HashValueImpl { static void apply(size_t& seed, Tuple const& tuple) { HashValueImpl<Tuple, Index-1>::apply(seed, tuple); hash_combine(seed, std::get<Index>(tuple)); } }; template <class Tuple> struct HashValueImpl<Tuple,0> { static void apply(size_t& seed, Tuple const& tuple) { hash_combine(seed, std::get<0>(tuple)); } }; } template <typename ... TT> struct hash<std::tuple<TT...>> { size_t operator()(std::tuple<TT...> const& tt) const { size_t seed = 0; HashValueImpl<std::tuple<TT...> >::apply(seed, tt); return seed; } }; }
unordered_set<tuple<double, int> > test_set;
Das obige ist der detaillierte Inhalt vonWie können Sie eine generische Hash-Funktion für Tupel in ungeordneten Sammlungen in C implementieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!