Rumah > pembangunan bahagian belakang > C++ > 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
Lepaskan: 2024-11-06 19:41:02
asal
873 orang telah melayarinya

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;                                 
        }                                              
    };
}
Salin selepas log masuk

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;                                 
        }                                              
    };
}
Salin selepas log masuk

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);                                 
    }                                              
};
}
Salin selepas log masuk

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;
Salin selepas log masuk

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 Laman Web ini
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan