From 90820f24a4ee9e1d1bc883db87994aaf6b06ae5b Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 9 Dec 2024 03:37:13 +0200 Subject: [PATCH] BAN: Make HashMap::{insert,emplace}{,_or_assign} return an iterator This reduces the number of lookups done into the hash map :) --- BAN/include/BAN/HashMap.h | 59 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/BAN/include/BAN/HashMap.h b/BAN/include/BAN/HashMap.h index 108259d6..ef2489db 100644 --- a/BAN/include/BAN/HashMap.h +++ b/BAN/include/BAN/HashMap.h @@ -45,27 +45,27 @@ namespace BAN HashMap& operator=(const HashMap&); HashMap& operator=(HashMap&&); - ErrorOr insert(const Key& key, const T& value) { return emplace(key, value); } - ErrorOr insert(const Key& key, T&& value) { return emplace(key, move(value)); } - ErrorOr insert(Key&& key, const T& value) { return emplace(move(key), value); } - ErrorOr insert(Key&& key, T&& value) { return emplace(move(key), move(value)); } + ErrorOr insert(const Key& key, const T& value) { return emplace(key, value); } + ErrorOr insert(const Key& key, T&& value) { return emplace(key, move(value)); } + ErrorOr insert(Key&& key, const T& value) { return emplace(move(key), value); } + ErrorOr insert(Key&& key, T&& value) { return emplace(move(key), move(value)); } - ErrorOr insert_or_assign(const Key& key, const T& value) { return emplace_or_assign(key, value); } - ErrorOr insert_or_assign(const Key& key, T&& value) { return emplace_or_assign(key, move(value)); } - ErrorOr insert_or_assign(Key&& key, const T& value) { return emplace_or_assign(move(key), value); } - ErrorOr insert_or_assign(Key&& key, T&& value) { return emplace_or_assign(move(key), move(value)); } + ErrorOr insert_or_assign(const Key& key, const T& value) { return emplace_or_assign(key, value); } + ErrorOr insert_or_assign(const Key& key, T&& value) { return emplace_or_assign(key, move(value)); } + ErrorOr insert_or_assign(Key&& key, const T& value) { return emplace_or_assign(move(key), value); } + ErrorOr insert_or_assign(Key&& key, T&& value) { return emplace_or_assign(move(key), move(value)); } template - ErrorOr emplace(const Key& key, Args&&... args) requires is_constructible_v + ErrorOr emplace(const Key& key, Args&&... args) requires is_constructible_v { return emplace(Key(key), forward(args)...); } template - ErrorOr emplace(Key&&, Args&&...) requires is_constructible_v; + ErrorOr emplace(Key&&, Args&&...) requires is_constructible_v; template - ErrorOr emplace_or_assign(const Key& key, Args&&... args) requires is_constructible_v + ErrorOr emplace_or_assign(const Key& key, Args&&... args) requires is_constructible_v { return emplace_or_assign(Key(key), forward(args)...); } template - ErrorOr emplace_or_assign(Key&&, Args&&...) requires is_constructible_v; + ErrorOr emplace_or_assign(Key&&, Args&&...) requires is_constructible_v; iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); } iterator end() { return iterator(m_buckets.end(), m_buckets.end()); } @@ -141,34 +141,35 @@ namespace BAN template template - ErrorOr HashMap::emplace(Key&& key, Args&&... args) requires is_constructible_v + ErrorOr::iterator> HashMap::emplace(Key&& key, Args&&... args) requires is_constructible_v { ASSERT(!contains(key)); TRY(rebucket(m_size + 1)); - auto& bucket = get_bucket(key); - TRY(bucket.emplace_back(move(key), forward(args)...)); + + auto bucket_it = get_bucket_iterator(key); + TRY(bucket_it->emplace_back(move(key), forward(args)...)); m_size++; - return {}; + + return iterator(m_buckets.end(), bucket_it, prev(bucket_it->end(), 1)); } template template - ErrorOr HashMap::emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v + ErrorOr::iterator> HashMap::emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v { if (empty()) return emplace(move(key), forward(args)...); - auto& bucket = get_bucket(key); - for (Entry& entry : bucket) + + auto bucket_it = get_bucket_iterator(key); + for (auto entry_it = bucket_it->begin(); entry_it != bucket_it->end(); entry_it++) { - if (entry.key == key) - { - entry.value = T(forward(args)...); - return {}; - } + if (entry_it->key != key) + continue; + entry_it->value = T(forward(args)...); + return iterator(m_buckets.end(), bucket_it, entry_it); } - TRY(bucket.emplace_back(move(key), forward(args)...)); - m_size++; - return {}; + + return emplace(move(key), forward(args)...); } template @@ -208,7 +209,7 @@ namespace BAN for (Entry& entry : bucket) if (entry.key == key) return entry.value; - ASSERT(false); + ASSERT_NOT_REACHED(); } template @@ -219,7 +220,7 @@ namespace BAN for (const Entry& entry : bucket) if (entry.key == key) return entry.value; - ASSERT(false); + ASSERT_NOT_REACHED(); } template