How do I combine hash values in C++0x?

boost hash combine
c++ hash<vector
combining hash values
std::hash
boost::hash_combine header
c custom hash function
the specified hash does not meet the hash requirements
template struct hash

C++0x adds hash<...>(...).

I could not find a hash_combine function though, as presented in boost. What is the cleanest way to implement something like this? Perhaps, using C++0x xor_combine?


Well, just do it like the boost guys did it:

template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

c++ - How do I combine hash values in C++0x?, Well, just do it like the boost guys did it: template <class T> inline void hash_combine(std::size_t& seed, const T& v) { std::hash<T> hasher; seed ^= hasher(v) +  The type of the first value to combine into the hash code. T2. The type of the second value to combine into the hash code. Parameters. value1 T1.


I'll share it here since it can be useful to others looking for this solution: starting from @KarlvonMoor answer, here's a variadic template version, which is terser in its usage if you have to combine several values together:

inline void hash_combine(std::size_t& seed) { }

template <typename T, typename... Rest>
inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
    hash_combine(seed, rest...);
}

Usage:

std::size_t h=0;
hash_combine(h, obj1, obj2, obj3);

This was written originally to implement a variadic macro to easily make custom types hashable (which I think is one of the primary usages of a hash_combine function):

#define MAKE_HASHABLE(type, ...) \
    namespace std {\
        template<> struct hash<type> {\
            std::size_t operator()(const type &t) const {\
                std::size_t ret = 0;\
                hash_combine(ret, __VA_ARGS__);\
                return ret;\
            }\
        };\
    }

Usage:

struct SomeHashKey {
    std::string key1;
    std::string key2;
    bool key3;
};

MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3)
// now you can use SomeHashKey as key of an std::unordered_map

std::hash - cppreference.com, Perhaps, using C++0x xor_combine ? Well, just do it like the boost guys did it: template <class T> inline void hash_combine(std::size_t& seed, const T& v)  Say you have two hashes H (A) and H (B) and you want to combine them. I've read that a good way to combine two hashes is to XOR them, e.g. XOR ( H (A), H (B) ). XORing two numbers with roughly random distribution results in another number still with roughly random distribution*, but which now depends on the two values.


This could also be solved by using a variadic template as follows:

#include <functional>

template <typename...> struct hash;

template<typename T> 
struct hash<T> 
    : public std::hash<T>
{
    using std::hash<T>::hash;
};


template <typename T, typename... Rest>
struct hash<T, Rest...>
{
    inline std::size_t operator()(const T& v, const Rest&... rest) {
        std::size_t seed = hash<Rest...>{}(rest...);
        seed ^= hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        return seed;
    }
};

Usage:

#include <string>

int main(int,char**)
{
    hash<int, float, double, std::string> hasher;
    std::size_t h = hasher(1, 0.2f, 2.0, "Hello World!");
}

One could certainly make a template function, but this could cause some nasty type deduction e.g hash("Hallo World!") will calculate a hash value on the pointer rather than on the string. This is probably the reason, why the standard uses a struct.

[PDF] Boost.Functional/Hash, There is no specialization for C strings. std::hash<const char*> produces a hash of the value of the pointer (the memory address), it does not  To do this we need to combine the hash values for x and y. The function boost::hash_combine is supplied for this purpose: class point { friend std::size_t hash_value(point const& p) { std::size_t seed = 0; boost::hash_combine(seed, p.x); boost::hash_combine(seed, p.y); return seed; }


A few days ago I came up with slightly improved version of this answer (C++ 17 support is required):

template <typename T, typename... Rest>
void hashCombine(uint& seed, const T& v, Rest... rest)
{
    seed ^= ::qHash(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    (hashCombine(seed, rest), ...);
}

The code above is better in terms of code generation. I used qHash function from Qt in my code, but it's also possible to use any other hashers.

Faster than 99.94% of C++ submissions, unordered_map, custom , combine the hash values for x and y. Ticket 3866: Don't foward declare containers when using gcc's parallel library, allow user to stop forward declaration by  To do this we need to combine the hash values for x and y. The function boost::hash_combine is supplied for this purpose: class point { friend std::size_t hash_value(point const& p) { std::size_t seed = 0; boost::hash_combine(seed, p.x); boost::hash_combine(seed, p.y); return seed; }


I really like the C++17 approach from the answer by vt4a2h, however it suffers from a problem: The Rest is passed on by value whereas it would be more desirable to pass them on by const references (which is a must if it shall be usable with move-only types).

Here is the adapted version which still uses a fold expression (which is the reason why it requires C++17 or above) and uses std::hash (instead of the Qt hash function):

template <typename T, typename... Rest>
void hash_combine(std::size_t& seed, const T& v, const Rest&... rest)
{
    seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
    (hash_combine(seed, rest), ...);
}

For completeness sake: All the types which shall be usable with this version of hash_combine must have a template specialization for hash injected into the std namespace.

Example:

namespace std // Inject hash for B into std::
{
    template<> struct hash<B>
    {
        std::size_t operator()(B const& b) const noexcept
        {
            std::size_t h = 0;
            cgb::hash_combine(h, b.firstMember, b.secondMember, b.andSoOn);
            return h;
        }
    };
}

So that type B in the example above is also usable within another type A, like the following usage example shows:

struct A
{
    std::string mString;
    int mInt;
    B mB;
    B* mPointer;
}

namespace std // Inject hash for A into std::
{
    template<> struct hash<A>
    {
        std::size_t operator()(A const& a) const noexcept
        {
            std::size_t h = 0;
            cgb::hash_combine(h,
                a.mString,
                a.mInt,
                a.mB, // calls the template specialization from above for B
                a.mPointer // does not call the template specialization but one for pointers from the standard template library
            );
            return h;
        }
    };
}

abseil / `absl::Hash`, This is based on frequencies of a string and a custom hash function to be .com/​questions/2590677/how-do-i-combine-hash-values-in-c0x. The third parameter to the definition is a function object type that is used by the class to convert a key into a hash code. By default it is set to std::hash<Key>. Internally the unordered_map class calls operator() on an object of that type in order to get a hash code for a given key. Note also


Simple-Web-Server/utility.hpp at master · eidheim/Simple-Web , The absl::Hash library consists of the following components: H AbslHashValue(​H h, const Circle& c) { return H::combine(std::move(h), c.center_, where the values passed should provide coverage for all interesting states of the object. specialization (aka __gnu_cxx::hash<T> for gcc/Clang or stdext::hash<T> for MSVC)  The situation I'm suggesting this for is where you want to do. H = hash(A) ^ hash(B); // A and B are different types, so there's no way A == B. of course, if A and B can be expected to hash to the same value with a reasonable (non-negligible) probability, then you should not use XOR in this way.


Combining hash values - 1.35.0, Combining hash values. Say you have a point class, representing a two dimensional location: class point { int x; int y; public: point() : x(0), y(0) {} point(int x, int y)  Unary function object class that defines the default hash function used by the standard library. The functional call returns a hash value of its argument: A hash value is a value that depends solely on its argument, returning always the same value for the same argument (for a given execution of a program).


Hashing, A hash container uses a hash value as an index to an array of subcontainers. After combining one part after the other in this way we have the resulting pre-​hash We might utilize the C++0x feature constexpr to calculate a manifest hash​  1. When doing initial load of data creating a hash value of all KEY fields to monitor added together, and store this hash value along with the data. 2. On import of new data into stage table, compare a hash summary of key fileds to hash value stored in database. If the hash values differed in any way, then this was an update, and passed on as such. 3.