Maison > développement back-end > C++ > Comment faire fonctionner `std::unordered_map` sans définir de fonction de hachage personnalisée ?

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
868 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!

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