>  기사  >  백엔드 개발  >  사용자 정의 해시 함수를 정의하지 않고 `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의 튜플에 대한 일반 해시

Q: 왜 std::unordered_map, 문자열> 즉시 사용 가능합니까?

표준 C에서 unordered_map 또는 unordered_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 및 hash_tuple 대응 항목이 있는 비준수 솔루션의 HashValueImpl. 마지막으로 다음 구문을 사용하십시오.

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

위 내용은 사용자 정의 해시 함수를 정의하지 않고 `std::unordered_map`이 작동하도록 만드는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.