"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > How to Implement a Generic Hash Function for Tuples in Unordered Collections?

How to Implement a Generic Hash Function for Tuples in Unordered Collections?

2025-03-28에 게시되었습니다
검색:106

How to Implement a Generic Hash Function for Tuples in Unordered Collections?

Generic Hash Function for Tuples in Unordered Collections

The std::unordered_map and std::unordered_set containers provide efficient lookup and insertion of elements based on their hashed values. However, using tuples as keys in these collections without defining a custom hash function can lead to unexpected behavior.

To rectify this, one approach is to manually define a hash function for the specific tuple type, such as:

template<>
struct std::hash<std::tuple<int, int>> {
  size_t operator()(std::tuple<int, int> const& tuple) const { ... }
};

While this approach works, it can be tedious to define hash functions for every tuple type used. To automate this, a generic hash function can be implemented as follows:

#include <tuple>

namespace std {
  namespace {

    // Code derived from Boost
    template<class T>
    inline void hash_combine(std::size_t& seed, T const& v) { ... }

    // Recursive template code from Matthieu M.
    template<class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
    struct HashValueImpl { ... };

  }

  template<typename... TT>
  struct hash<std::tuple<TT...>> {
    size_t operator()(std::tuple<TT...> const& tuple) const { ... }
  };
}

This function leverages argument-dependent name lookup (ADL) to allow the compiler to automatically select the correct hash implementation based on the tuple type.

Standard Conformant Solution

It is worth noting that defining non-standard functions in the std namespace is undefined behavior. For a standards-compliant solution, a custom namespace can be created and used to define the hash function:

namespace my_hash {

  // Forward non-tuple types to the std::hash
  template<typename TT>
  struct hash { ... };

  // Provide the optimized hash for tuples
  template<typename... TT>
  struct hash<std::tuple<TT...>> { ... };

}

When using this solution, the unordered collection must explicitly reference the custom hash implementation as follows:

unordered_set<
  std::tuple<double, int>,
  std::hash<std::tuple<double, int>>,
  std::equal_to<std::tuple<double, int>>
> test;  
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3