Home  >  Article  >  Backend Development  >  How to Implement a Generic Hash Function for Tuples in Unordered Collections?

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

DDD
DDDOriginal
2024-11-15 09:21:02431browse

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;  

The above is the detailed content of How to Implement a Generic Hash Function for Tuples in Unordered Collections?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn