From 6f91dc796285d2ec1a2e21960ff9f30c232eef2a Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 29 Apr 2019 17:12:20 -0400 Subject: [PATCH] support the boost hash_value() method for providing hash value. --- README.md | 32 +++++++++++++++++++++++++++++++- parallel_hashmap/phmap.h | 31 ++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2b6784d..7761e55 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,37 @@ The rules are the same as for std::unordered_map, and are valid for all the phma ## Example 2 - providing a hash function for a user-defined class -In order to use a flat_hash_set or flat_hash_map, a hash function should be provided. Even though a the hash function can be provided via the HashFcn template parameter, we recommend injecting a specialization of `std::hash` for the class into the "std" namespace. We provide a convenient and small header `phmap_utils.h` which allows to easily add such specializations. +In order to use a flat_hash_set or flat_hash_map, a hash function should be provided. This can be done with one of the following methods: + +- Provide a hash functor via the HashFcn template parameter + +- As with boost, you may add a `hash_value()` friend function in your class. + +For example: + +```c++ +#include // minimal header providing phmap::HashState() +#include +using std::string; + +struct Person +{ + bool operator==(const Person &o) const + { + return _first == o._first && _last == o._last && _age == o._age; + } + + friend size_t hash_value(const Person &p) + { + return phmap::HashState().combine(0, p._first, p._last, p._age); + } + + string _first; + string _last; + int _age; +}; + +- Inject a specialization of `std::hash` for the class into the "std" namespace. We provide a convenient and small header `phmap_utils.h` which allows to easily add such specializations. For example: diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index e80279f..d046ef4 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -135,17 +135,46 @@ struct fold_if_needed<8> } }; +// --------------------------------------------------------------- +// see if class T has a hash_value() friend method +// --------------------------------------------------------------- +template +struct has_hash_value +{ +private: + typedef std::true_type yes; + typedef std::false_type no; + template static auto test(int) -> decltype(hash_value(std::declval()) == 1, yes()); + + template static no test(...); + +public: + static constexpr bool value = std::is_same(0)), yes>::value; +}; + // --------------------------------------------------------------- // phmap::Hash // --------------------------------------------------------------- template struct Hash { - inline size_t operator()(const T& val) const + template ::value, int>::type = 0> + size_t _hash(const T& val) const + { + return hash_value(val); + } + + template ::value, int>::type = 0> + size_t _hash(const T& val) const { return std::hash()(val); } + + inline size_t operator()(const T& val) const + { + return _hash(val); + } }; template