forked from scylladb/scylladb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhash.hh
73 lines (63 loc) · 2.1 KB
/
hash.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
* Copyright (C) 2015-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#ifndef UTILS_HASH_HH_
#define UTILS_HASH_HH_
#include <functional>
namespace utils {
// public for unit testing etc
inline size_t hash_combine(size_t left, size_t right) {
return left + 0x9e3779b9 + (right << 6) + (right >> 2);
}
struct tuple_hash {
private:
// CMH. Add specializations here to handle recursive tuples
template<typename T>
static size_t hash(const T& t) {
return std::hash<T>()(t);
}
template<size_t index, typename...Types>
struct hash_impl {
size_t operator()(const std::tuple<Types...>& t, size_t a) const {
return hash_impl<index-1, Types...>()(t, hash_combine(hash(std::get<index>(t)), a));
}
size_t operator()(const std::tuple<Types...>& t) const {
return hash_impl<index-1, Types...>()(t, hash(std::get<index>(t)));
}
};
template<class...Types>
struct hash_impl<0, Types...> {
size_t operator()(const std::tuple<Types...>& t, size_t a) const {
return hash_combine(hash(std::get<0>(t)), a);
}
size_t operator()(const std::tuple<Types...>& t) const {
return hash(std::get<0>(t));
}
};
public:
// All the operator() implementations are templates, so this is transparent.
using is_transparent = void;
template<typename T1, typename T2>
size_t operator()(const std::pair<T1, T2>& p) const {
return hash_combine(hash(p.first), hash(p.second));
}
template<typename T1, typename T2>
size_t operator()(const T1& t1, const T2& t2) const {
return hash_combine(hash(t1), hash(t2));
}
template<typename... Args>
size_t operator()(const std::tuple<Args...>& v) const;
};
template<typename... Args>
inline size_t tuple_hash::operator()(const std::tuple<Args...>& v) const {
return hash_impl<std::tuple_size<std::tuple<Args...>>::value - 1, Args...>()(v);
}
template<>
inline size_t tuple_hash::operator()(const std::tuple<>& v) const {
return 0;
}
}
#endif /* UTILS_HASH_HH_ */