Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk Membuat `std::unordered_map` Berfungsi Tanpa Menentukan Fungsi Hash Tersuai?

Bagaimana untuk Membuat `std::unordered_map` Berfungsi Tanpa Menentukan Fungsi Hash Tersuai?

Barbara Streisand
Barbara Streisandasal
2024-11-06 19:41:02739semak imbas

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

Generik Hash untuk Tuples dalam unordered_map/unordered_set

S: Mengapa tidak std::unordered_map, rentetan> bekerja di luar kotak?

Dalam standard C , untuk menggunakan tupel sebagai kunci dalam bekas bersekutu seperti unordered_map atau unordered_set, anda perlu menentukan fungsi cincang tersuai.

S: Bolehkah ini diautomatikkan untuk tuple C 0x tanpa menggunakan templat variadic?

Ya, menggunakan kod berikut:

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;                                 
        }                                              
    };
}

S: Adakah terdapat penyelesaian yang lebih mudah ?

Penyelesaian Tidak Mematuhi Standard (ADL Didayakan):

#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;                                 
        }                                              
    };
}

Penyelesaian Pematuhan Standard (Tiada ADL):

Untuk mencapai pematuhan standard yang ketat, anda mesti mengalihkan kod di atas ke ruang nama yang berasingan (cth., hash_tuple) dan mengubah suai sintaks untuk menentukan fungsi cincang tersuai secara eksplisit.

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);                                 
    }                                              
};
}

Ganti hash_combine dan HashValueImpl daripada penyelesaian tidak akur dengan rakan sejawat hash_tuple mereka. Akhir sekali, gunakan sintaks berikut:

unordered_set<tuple<double, int>, hash_tuple::hash<tuple<double, int>>> test2;

Atas ialah kandungan terperinci Bagaimana untuk Membuat `std::unordered_map` Berfungsi Tanpa Menentukan Fungsi Hash Tersuai?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn