|
@@ -14,28 +14,29 @@ namespace types {
|
|
|
constexpr uint32_t GOLDEN_RATIO_32 = 0x61C88647;
|
|
|
// constexpr uint64_t GOLDEN_RATIO_64 = 0x61C8864680B583EBull;
|
|
|
|
|
|
-static constexpr uint32_t _hash32(uint32_t val)
|
|
|
+using hash_t = size_t;
|
|
|
+
|
|
|
+static inline constexpr hash_t _hash32(uint32_t val)
|
|
|
{
|
|
|
return val * GOLDEN_RATIO_32;
|
|
|
}
|
|
|
|
|
|
-static constexpr uint32_t hash32(uint32_t val, uint32_t bits)
|
|
|
+static inline constexpr hash_t hash32(uint32_t val, uint32_t bits)
|
|
|
{
|
|
|
// higher bits are more random
|
|
|
return _hash32(val) >> (32 - bits);
|
|
|
}
|
|
|
|
|
|
-template <typename T>
|
|
|
+template <convertible_to<uint32_t> T>
|
|
|
struct linux_hasher {
|
|
|
- static constexpr uint32_t hash(const T& val, uint32_t bits)
|
|
|
+ static inline constexpr hash_t hash(T val, uint32_t bits)
|
|
|
{
|
|
|
- return hash32(val, bits);
|
|
|
+ return hash32(static_cast<uint32_t>(val), bits);
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
template <typename T>
|
|
|
struct linux_hasher<T*> {
|
|
|
- static constexpr uint32_t hash(T* val, uint32_t bits)
|
|
|
+ static inline constexpr hash_t hash(T* val, uint32_t bits)
|
|
|
{
|
|
|
return hash32(reinterpret_cast<uint32_t>(val), bits);
|
|
|
}
|
|
@@ -43,15 +44,15 @@ struct linux_hasher<T*> {
|
|
|
|
|
|
template <typename T>
|
|
|
struct string_hasher {
|
|
|
- static constexpr uint32_t hash(T, uint32_t)
|
|
|
+ static inline constexpr hash_t hash(T, uint32_t)
|
|
|
{
|
|
|
static_assert(types::template_false_type<T>::value, "string hasher does not support this type");
|
|
|
- return (uint32_t)0;
|
|
|
+ return (hash_t)0;
|
|
|
}
|
|
|
};
|
|
|
template <>
|
|
|
struct string_hasher<const char*> {
|
|
|
- static constexpr uint32_t hash(const char* str, uint32_t bits)
|
|
|
+ static inline constexpr hash_t hash(const char* str, uint32_t bits)
|
|
|
{
|
|
|
constexpr uint32_t seed = 131;
|
|
|
uint32_t hash = 0;
|
|
@@ -64,7 +65,7 @@ struct string_hasher<const char*> {
|
|
|
};
|
|
|
template <template <typename> class Allocator>
|
|
|
struct string_hasher<const types::string<Allocator>&> {
|
|
|
- static inline constexpr uint32_t hash(const types::string<Allocator>& str, uint32_t bits)
|
|
|
+ static inline constexpr hash_t hash(const types::string<Allocator>& str, uint32_t bits)
|
|
|
{
|
|
|
return string_hasher<const char*>::hash(str.c_str(), bits);
|
|
|
}
|
|
@@ -77,17 +78,15 @@ struct string_hasher<types::string<Allocator>&&> {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-template <class Hasher, typename Value>
|
|
|
-struct hasher_traits {
|
|
|
- using hash_t = size_t;
|
|
|
- using length_t = size_t;
|
|
|
- static constexpr hash_t hash(Value val, length_t bits)
|
|
|
+template <typename _Hasher, typename Value>
|
|
|
+concept Hasher = requires(Value&& val, uint32_t bits)
|
|
|
+{
|
|
|
{
|
|
|
- return Hasher::hash(val, bits);
|
|
|
- }
|
|
|
+ _Hasher::hash(val, bits)
|
|
|
+ } -> convertible_to<size_t>;
|
|
|
};
|
|
|
|
|
|
-template <typename Key, typename Value, typename Hasher, template <typename _T> class Allocator = types::kernel_allocator>
|
|
|
+template <typename Key, typename Value, Hasher<Key> _Hasher, template <typename _T> class Allocator = types::kernel_allocator>
|
|
|
class hash_map {
|
|
|
public:
|
|
|
struct pair;
|
|
@@ -227,12 +226,12 @@ public:
|
|
|
|
|
|
void insert(const pair& p)
|
|
|
{
|
|
|
- auto hash_value = hasher_traits<Hasher, key_type>::hash(p.key, hash_length());
|
|
|
+ auto hash_value = _Hasher::hash(p.key, hash_length());
|
|
|
buckets.at(hash_value).push_back(p);
|
|
|
}
|
|
|
void insert(pair&& p)
|
|
|
{
|
|
|
- auto hash_value = hasher_traits<Hasher, key_type>::hash(p.key, hash_length());
|
|
|
+ auto hash_value = _Hasher::hash(p.key, hash_length());
|
|
|
buckets.at(hash_value).push_back(move(p));
|
|
|
}
|
|
|
void insert(const key_type& key, const value_type& val)
|
|
@@ -242,7 +241,7 @@ public:
|
|
|
|
|
|
void remove(const key_type& key)
|
|
|
{
|
|
|
- auto hash_value = hasher_traits<Hasher, key_type>::hash(key, hash_length());
|
|
|
+ auto hash_value = _Hasher::hash(key, hash_length());
|
|
|
auto& bucket = buckets.at(hash_value);
|
|
|
for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) {
|
|
|
if (iter->key == key) {
|
|
@@ -254,7 +253,7 @@ public:
|
|
|
|
|
|
iterator_type find(const key_type& key)
|
|
|
{
|
|
|
- auto hash_value = hasher_traits<Hasher, key_type>::hash(key, hash_length());
|
|
|
+ auto hash_value = _Hasher::hash(key, hash_length());
|
|
|
auto& bucket = buckets.at(hash_value);
|
|
|
for (auto& item : bucket) {
|
|
|
if (key == item.key)
|
|
@@ -265,7 +264,7 @@ public:
|
|
|
|
|
|
const_iterator_type find(const key_type& key) const
|
|
|
{
|
|
|
- auto hash_value = hasher_traits<Hasher, key_type>::hash(key, hash_length());
|
|
|
+ auto hash_value = _Hasher::hash(key, hash_length());
|
|
|
const auto& bucket = buckets.at(hash_value);
|
|
|
for (const auto& item : bucket) {
|
|
|
if (key == item.key)
|