Heim > Backend-Entwicklung > C++ > Wie kann „std::unordered_map' funktionieren, ohne eine benutzerdefinierte Hash-Funktion zu definieren?

Wie kann „std::unordered_map' funktionieren, ohne eine benutzerdefinierte Hash-Funktion zu definieren?

Barbara Streisand
Freigeben: 2024-11-06 19:41:02
Original
847 Leute haben es durchsucht

How to Make `std::unordered_map` Work Without Defining a Custom Hash Function?

Generischer Hash für Tupel in unordered_map/unordered_set

F: Warum funktioniert std::unordered_map, string> funktionieren sofort?

Um in Standard-C Tupel als Schlüssel in assoziativen Containern wie unordered_map oder unordered_set zu verwenden, müssen Sie eine benutzerdefinierte Hash-Funktion definieren.

F: Kann dies für C 0x-Tupel automatisiert werden, ohne variadische Vorlagen zu verwenden?

Ja, unter Verwendung des folgenden Codes:

namespace std{
    namespace
    {
        template <class T>
        inline void hash_combine(std::size_t&amp; seed, T const&amp; v)
        {
            seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
        }

        template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
        struct HashValueImpl
        {
          static void apply(size_t&amp; seed, Tuple const&amp; 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&amp; seed, Tuple const&amp; tuple)
          {
            hash_combine(seed, std::get<0>(tuple));
          }
        };
    }

    template <typename ... TT>
    struct hash<std::tuple<TT...>> 
    {
        size_t
        operator()(std::tuple<TT...> const&amp; tt) const
        {                                              
            size_t seed = 0;                             
            HashValueImpl<std::tuple<TT...> >::apply(seed, tt);    
            return seed;                                 
        }                                              
    };
}
Nach dem Login kopieren

F: Gibt es eine einfachere Lösung? ?

Standard-nicht-konforme Lösung (ADL-fähig):

#include 
namespace std{
    namespace
    {
        template <class T>
        inline void hash_combine(std::size_t&amp; seed, T const&amp; v)
        {
            seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
        }

        template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
        struct HashValueImpl
        {
          static void apply(size_t&amp; seed, Tuple const&amp; 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&amp; seed, Tuple const&amp; tuple)
          {
            hash_combine(seed, std::get<0>(tuple));
          }
        };
    }

    template <typename ... TT>
    struct hash<std::tuple<TT...>> 
    {
        size_t
        operator()(std::tuple<TT...> const&amp; tt) const
        {                                              
            size_t seed = 0;                             
            HashValueImpl<std::tuple<TT...> >::apply(seed, tt);    
            return seed;                                 
        }                                              
    };
}
Nach dem Login kopieren

Standard-konforme Lösung (kein ADL):

Um eine strikte Standardkonformität zu erreichen, müssen Sie den obigen Code in einen separaten Namespace (z. B. hash_tuple) verschieben und die Syntax ändern, um die benutzerdefinierte Hash-Funktion explizit anzugeben.

namespace hash_tuple{

// Forward non-tuple types to std::hash
template <typename TT>
struct hash
{
    size_t
    operator()(TT const&amp; tt) const
    {                                              
        return std::hash<TT>()(tt);                                 
    }                                              
};
}
Nach dem Login kopieren

Ersetzen Sie hash_combine und HashValueImpl aus der nicht konformen Lösung mit ihren hash_tuple-Gegenstücken. Verwenden Sie abschließend die folgende Syntax:

unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonWie kann „std::unordered_map' funktionieren, ohne eine benutzerdefinierte Hash-Funktion zu definieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage