Home > Article > Backend Development > 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!