Maison > développement back-end > C++ > le corps du texte

Comment faire fonctionner `std::unordered_map` sans définir de fonction de hachage personnalisée ?

Barbara Streisand
Libérer: 2024-11-06 19:41:02
original
738 Les gens l'ont consulté

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

Hash générique pour les tuples dans unordered_map/unordered_set

Q : Pourquoi std::unordered_map, chaîne> fonctionne-t-il immédiatement ?

En C standard, pour utiliser des tuples comme clés dans des conteneurs associatifs comme unordered_map ou unordered_set, vous devez définir une fonction de hachage personnalisée.

Q : Cela peut-il être automatisé pour les tuples C 0x sans utiliser de modèles variadiques ?

Oui, en utilisant le code suivant :

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;                                 
        }                                              
    };
}
Copier après la connexion

Q : Existe-t-il une solution plus simple ?

Solution standard non conforme (ADL activée) :

#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;                                 
        }                                              
    };
}
Copier après la connexion

Solution conforme aux standards (Non ADL) :

Pour obtenir une conformité stricte aux normes, vous devez déplacer le code ci-dessus dans un espace de noms distinct (par exemple, hash_tuple) et modifier la syntaxe pour spécifier explicitement la fonction de hachage personnalisée.

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);                                 
    }                                              
};
}
Copier après la connexion

Remplacez hash_combine et HashValueImpl de la solution non conforme par leurs homologues hash_tuple. Enfin, utilisez la syntaxe suivante :

unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!