summaryrefslogtreecommitdiff
path: root/src/hash.hh
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-12-16 18:57:19 +0000
committerMaxime Coste <frrrwww@gmail.com>2014-12-16 18:57:19 +0000
commitebecd60eb810246cfa682a1fbd72270aa9861f0b (patch)
tree0c5c707b68cb08fc93ace2433291deb8a52db5bc /src/hash.hh
parentdbd7bd41bbf39d1fd5736997122a4652c78ddc50 (diff)
Rework hashing, use a more extensible framework similar to n3876 proposal
std::hash specialization is a pain to work with, stop using that, and just specialize a 'size_t hash_value(const T&)' free function.
Diffstat (limited to 'src/hash.hh')
-rw-r--r--src/hash.hh57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/hash.hh b/src/hash.hh
new file mode 100644
index 00000000..838fdffa
--- /dev/null
+++ b/src/hash.hh
@@ -0,0 +1,57 @@
+#ifndef hash_hh_INCLUDED
+#define hash_hh_INCLUDED
+
+#include <type_traits>
+#include <functional>
+
+namespace Kakoune
+{
+
+size_t hash_data(const char* data, size_t len);
+
+template<typename Type>
+typename std::enable_if<not std::is_enum<Type>::value, size_t>::type
+hash_value(const Type& val)
+{
+ return std::hash<Type>()(val);
+}
+
+template<typename Type>
+typename std::enable_if<std::is_enum<Type>::value, size_t>::type
+hash_value(const Type& val)
+{
+ return hash_value((typename std::underlying_type<Type>::type)val);
+}
+
+template<typename Type>
+size_t hash_values(Type&& t)
+{
+ return hash_value(std::forward<Type>(t));
+}
+
+template<typename Type, typename... RemainingTypes>
+size_t hash_values(Type&& t, RemainingTypes&&... rt)
+{
+ size_t seed = hash_values(std::forward<RemainingTypes>(rt)...);
+ return seed ^ (hash_value(std::forward<Type>(t)) + 0x9e3779b9 +
+ (seed << 6) + (seed >> 2));
+}
+
+template<typename T1, typename T2>
+size_t hash_value(const std::pair<T1, T2>& val)
+{
+ return hash_values(val.first, val.second);
+}
+
+template<typename Type>
+struct Hash
+{
+ size_t operator()(const Type& val) const
+ {
+ return hash_value(val);
+ }
+};
+
+}
+
+#endif // hash_hh_INCLUDED