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

boost::hash_combine implementation
std::hash
boost hash combine
combining hash values
c combine hashes
0x9e3779b9
hash function for strings c++
specialize std::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);
}

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) : x(x), y(y) {} bool operator==(point const& other) const { return x == other. x && y == other. 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

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

[PDF] Convenience Functions to Combine Hash Values, Convenience Functions to Combine Hash. Values. Currently, there is not support in C++ to define hash functions for user-defined keys. Instead,. Xor may be the "default" way to combine hashes but Greg Hewgill's answer also shows why it has its pitfalls: The xor of two identical hash values is zero. In real life, there are identical hashes are more common than one might have expected.

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] hash_combine() Again, In 2012, N3333 “Hashing User-Defined Types in C++1y”. • In 2014, N3976 “ Convenience Functions to Combine Hash Values”. N3976 was� A module PrintKeyItems get the hash, the key to find, and the second array with values, and apply indexes from hash to array. The MakeHash add indexes using start value of array of values. So we can pass arrays with different start and end index, but they must be one dimension and have same number of items, else we get error

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.

Combining hash values, Combining hash values. @interface MyDateRange @property (readwrite) NSDate *start; @property (readwrite) NSDate *end; @end. - (NSUInteger)hash { return start. template <typename SizeT> inline void hash_combine_impl(SizeT& seed, SizeT value) { seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); } For every type Key for which neither the library nor the user provides an enabled specialization std::hash<Key>, that specialization exists and is disabled. Disabled specializations do not satisfy Hash, do not satisfy FunctionObject, and following values are all false: std:: is_default_constructible < std:: hash < Key >>:: value

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;
        }
    };
}

How do I combine hash values in C++0x?, 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 Create combined hash bytes Hash(params object[] values) String from hash bytes String(byte[] hash) Methods We Are Going to Use More Frequently. Create a hash string of any string HashString(string value, Encoding encoding = null) Create hash/combine hash string of any/group of object HashString(params object[] values) Hash of Entire Object

Combining hash values, Boost C++ Libraries 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� Note that it's a generic method, which avoids boxing for value types. It copes with null values automatically (using 0 for the value). Note that the MakeHash method has an unchecked block as Noda Time uses checked arithmetic as a project setting, whereas hash code calculations should be allowed to overflow.

std::hash - cppreference.com, 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� You have now created a function, hash(), which will calculate and print out the hash value for a given string using the MD5 hashing algorithm. To run it, put a string in between the parentheses in

How do I combine hash values in C++0x?, 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 � Hash codes are used to insert and retrieve keyed objects from hash tables efficiently. However, hash codes don't uniquely identify strings. Identical strings have equal hash codes, but the common language runtime can also assign the same hash code to different strings.

Comments
  • yeah, that's the best I could do too. I don't understand how the standards committee declined something so obvious.
  • @Neil: I agree. I think a simple solution for them would be the requirement of the library to have a hash for std::pair (or tuple, even). It would compute the hash of each element, then combine them. (And in the spirit of the standard library, in an implementation defined way.)
  • There are a lot of obvious things omitted from the standard. The process of intensive peer review makes it difficult to get those little things out the door.
  • Why these magic numbers here? And isn't the above machine-dependent (e.g. won't it be different on x86 and x64 platforms)?
  • There's a paper suggesting the inclusion of hash_combine here
  • Why is the seed always bitshifted by 6 and 2, respectively?
  • 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 examine the contents of any character array. Cref: en.cppreference.com/w/cpp/utility/hash
  • Write the fold expression as (int[]){0, (hashCombine(seed, rest), 0)...}; and it'll also work in C++11.
  • In my opinion it is nicer to use the Hash template arguments of the standard containers to specify your custom hasher instead of injecting it into the std namespace.
  • Looks much better, thank you! I probably didn't care about passing by value, because I used some implicitly shared objects, for example, like QString.