Heim  >  Artikel  >  Backend-Entwicklung  >  Wie implementiert man eine generische Hash-Funktion für Tupel in ungeordneten Sammlungen?

Wie implementiert man eine generische Hash-Funktion für Tupel in ungeordneten Sammlungen?

DDD
DDDOriginal
2024-11-15 09:21:02431Durchsuche

How to Implement a Generic Hash Function for Tuples in Unordered Collections?

Generische Hash-Funktion für Tupel in ungeordneten Sammlungen

Die Container std::unordered_map und std::unordered_set ermöglichen ein effizientes Suchen und Einfügen von Elementen basierend auf ihren gehashten Werten. Allerdings kann die Verwendung von Tupeln als Schlüssel in diesen Sammlungen ohne Definition einer benutzerdefinierten Hash-Funktion zu unerwartetem Verhalten führen.

Um dies zu beheben, besteht ein Ansatz darin, manuell eine Hash-Funktion für den spezifischen Tupeltyp zu definieren, wie zum Beispiel:

template<>
struct std::hash<std::tuple<int, int>> {
  size_t operator()(std::tuple<int, int> const& tuple) const { ... }
};

Obwohl dieser Ansatz funktioniert, kann es mühsam sein, Hash-Funktionen für jeden verwendeten Tupeltyp zu definieren. Um dies zu automatisieren, kann eine generische Hash-Funktion wie folgt implementiert werden:

#include <tuple>

namespace std {
  namespace {

    // Code derived from Boost
    template<class T>
    inline void hash_combine(std::size_t& seed, T const& v) { ... }

    // Recursive template code from Matthieu M.
    template<class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
    struct HashValueImpl { ... };

  }

  template<typename... TT>
  struct hash<std::tuple<TT...>> {
    size_t operator()(std::tuple<TT...> const& tuple) const { ... }
  };
}

Diese Funktion nutzt die argumentabhängige Namenssuche (ADL), um dem Compiler zu ermöglichen, automatisch die richtige Hash-Implementierung basierend auf dem Tupeltyp auszuwählen .

Standardkonforme Lösung

Es ist erwähnenswert, dass die Definition nicht standardmäßiger Funktionen in der std-Namespace ist undefiniertes Verhalten. Für eine standardkonforme Lösung kann ein benutzerdefinierter Namespace erstellt und zum Definieren der Hash-Funktion verwendet werden:

namespace my_hash {

  // Forward non-tuple types to the std::hash
  template<typename TT>
  struct hash { ... };

  // Provide the optimized hash for tuples
  template<typename... TT>
  struct hash<std::tuple<TT...>> { ... };

}

Bei Verwendung dieser Lösung muss die ungeordnete Sammlung explizit auf die benutzerdefinierte Hash-Implementierung wie folgt verweisen:

unordered_set<
  std::tuple<double, int>,
  std::hash<std::tuple<double, int>>,
  std::equal_to<std::tuple<double, int>>
> test;  

Das obige ist der detaillierte Inhalt vonWie implementiert man eine generische Hash-Funktion für Tupel in ungeordneten Sammlungen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn