ホームページ >バックエンド開発 >C++ >カスタムハッシュ関数を定義せずに「std::unowned_map」を機能させるにはどうすればよいですか?

カスタムハッシュ関数を定義せずに「std::unowned_map」を機能させるにはどうすればよいですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-11-06 19:41:02823ブラウズ

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

unowned_map/unowned_set のタプルの汎用ハッシュ

Q: なぜ std::unowned_map、string>すぐに使えますか?

標準 C では、unowned_map や unowned_set などの連想コンテナーでタプルをキーとして使用するには、カスタム ハッシュ関数を定義する必要があります。

Q: 可変個引数テンプレートを使用せずに 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;                                 
        }                                              
    };
}<p><strong>Q: より簡単な解決策はありますか? ?</strong></p>
<p><strong>標準非準拠ソリューション (ADL 有効):</strong></p>
<pre class="brush:php;toolbar:false">#include <tuple>
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::unowned_map」を機能させるにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。