首頁  >  文章  >  後端開發  >  如何在不定義自訂雜湊函數的情況下使“std::unordered_map”工作?

如何在不定義自訂雜湊函數的情況下使“std::unordered_map”工作?

Barbara Streisand
Barbara Streisand原創
2024-11-06 19:41:02739瀏覽

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

unordered_map/unordered_set 中元組的通用雜湊

問:為什麼std::unordered_map,字串>開箱即用?

在標準 C 中,要使用元組作為關聯容器(如 unordered_map 或 unordered_set)中的鍵,您需要定義自訂雜湊函數。

問:可以在不使用可變參數模板的情況下對 C 0x 元組進行自動化嗎?

可以,使用以下程式碼:

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

問:是否有更簡單的解?

標準不合格解決方案(啟用ADL):

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

標準合格解決方案(無ADL):

為了達到嚴格的標準一致性,您必須將上述程式碼移至單獨的命名空間(例如hash_tuple)中,並修改語法以明確指定自訂雜湊函數。

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

取代 hash_combine 和來自不合格解決方案的 HashValueImpl 及其 hash_tuple 對應項。最後,使用以下語法:

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

以上是如何在不定義自訂雜湊函數的情況下使“std::unordered_map”工作?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn