diff --git a/octa/internal/hashtable.h b/octa/internal/hashtable.h index 2c75f27..348f5d8 100644 --- a/octa/internal/hashtable.h +++ b/octa/internal/hashtable.h @@ -140,7 +140,8 @@ namespace detail { typename T, /* value type */ typename H, /* hash func */ typename C, /* equality check */ - typename A /* allocator */ + typename A, /* allocator */ + bool Multihash > struct Hashtable { static constexpr octa::Size CHUNKSIZE = 64; @@ -328,7 +329,6 @@ namespace detail { return B::get_data(c->value); } - template octa::Size remove(const K &key) { if (!p_len) return 0; octa::Size olen = p_len; @@ -342,7 +342,7 @@ namespace detail { p_unused = c; octa::allocator_destroy(get_alloc(), &c->value); octa::allocator_construct(get_alloc(), &c->value); - if (!multi) return 1; + if (!Multihash) return 1; } else { p = &c->next; } @@ -351,7 +351,6 @@ namespace detail { return olen - p_len; } - template octa::Size count(const K &key) { if (!p_len) return 0; octa::Size h = get_hash()(key) & (p_size - 1); @@ -359,7 +358,7 @@ namespace detail { for (Chain *c = p_data.first()[h]; c; c = c->next) if (get_eq()(key, B::get_key(c->value))) { ++ret; - if (!multi) break; + if (!Multihash) break; } return ret; } @@ -407,6 +406,14 @@ namespace detail { rehash_ahead(1); E elem(octa::forward(args)...); octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1); + if (Multihash) { + /* multihash: always insert */ + Chain *ch = insert(h); + B::swap_elem(ch->value, elem); + Chain **hch = p_data.first(); + return octa::make_pair(Range(hch + h + 1, hch + bucket_count(), + ch), true); + } Chain *found = nullptr; bool ins = true; for (Chain *c = p_data.first()[h]; c; c = c->next) { @@ -425,18 +432,6 @@ namespace detail { found), ins); } - template - octa::Pair emplace_multi(Args &&...args) { - rehash_ahead(1); - E elem(octa::forward(args)...); - octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1); - Chain *ch = insert(h); - B::swap_elem(ch->value, elem); - Chain **hch = p_data.first(); - return octa::make_pair(Range(hch + h + 1, hch + bucket_count(), - ch), true); - } - bool find(const K &key, octa::Size &h, Chain *&oc) const { if (!p_size) return false; h = get_hash()(key) & (p_size - 1); diff --git a/octa/map.h b/octa/map.h index d7d36ed..5922754 100644 --- a/octa/map.h +++ b/octa/map.h @@ -47,7 +47,8 @@ template< > struct Map { private: using Base = octa::detail::Hashtable< - octa::detail::MapBase, octa::Pair, K, T, H, C, A + octa::detail::MapBase, octa::Pair, + K, T, H, C, A, false >; Base p_table; @@ -197,11 +198,11 @@ public: } octa::Size erase(const K &key) { - return p_table.remove(key); + return p_table.remove(key); } octa::Size count(const K &key) { - return p_table.count(key); + return p_table.count(key); } Range find(const K &key) { return p_table.find(key); } @@ -241,7 +242,7 @@ template< private: using Base = octa::detail::Hashtable< octa::detail::MapBase, octa::Pair, - K, T, H, C, A + K, T, H, C, A, true >; Base p_table; @@ -368,15 +369,15 @@ public: template octa::Pair emplace(Args &&...args) { - return p_table.emplace_multi(octa::forward(args)...); + return p_table.emplace(octa::forward(args)...); } octa::Size erase(const K &key) { - return p_table.remove(key); + return p_table.remove(key); } octa::Size count(const K &key) { - return p_table.count(key); + return p_table.count(key); } Range find(const K &key) { return p_table.find(key); } diff --git a/octa/set.h b/octa/set.h index 0971828..768d612 100644 --- a/octa/set.h +++ b/octa/set.h @@ -38,7 +38,7 @@ template< > struct Set { private: using Base = octa::detail::Hashtable< - octa::detail::SetBase, T, T, T, H, C, A + octa::detail::SetBase, T, T, T, H, C, A, false >; Base p_table; @@ -165,11 +165,11 @@ public: } octa::Size erase(const T &key) { - return p_table.remove(key); + return p_table.remove(key); } octa::Size count(const T &key) { - return p_table.count(key); + return p_table.count(key); } Range find(const Key &key) { return p_table.find(key); } @@ -208,7 +208,7 @@ template< > struct Multiset { private: using Base = octa::detail::Hashtable< - octa::detail::SetBase, T, T, T, H, C, A + octa::detail::SetBase, T, T, T, H, C, A, true >; Base p_table; @@ -334,15 +334,15 @@ public: template octa::Pair emplace(Args &&...args) { - return p_table.emplace_multi(octa::forward(args)...); + return p_table.emplace(octa::forward(args)...); } octa::Size erase(const T &key) { - return p_table.remove(key); + return p_table.remove(key); } octa::Size count(const T &key) { - return p_table.count(key); + return p_table.count(key); } Range find(const T &key) { return p_table.find(key); }