1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:04:59 +00:00

AK: Allow HashMap to be used with non-default-constructible values.

Solve this by adding find() overloads to HashTable and SinglyLinkedList
that take a templated functor for comparing the values.

This allows HashMap to call HashTable::find() without having to create
a temporary Entry for use as the table key. :^)
This commit is contained in:
Andreas Kling 2019-06-29 21:09:40 +02:00
parent d5bb98acbc
commit 6e95b11395
3 changed files with 67 additions and 51 deletions

View file

@ -146,8 +146,42 @@ public:
ConstIterator begin() const { return ConstIterator(*this, is_empty()); }
ConstIterator end() const { return ConstIterator(*this, true); }
Iterator find(const T&);
ConstIterator find(const T&) const;
template<typename Finder>
Iterator find(unsigned hash, Finder finder)
{
if (is_empty())
return end();
int bucket_index;
auto& bucket = lookup_with_hash(hash, &bucket_index);
auto bucket_iterator = bucket.find(finder);
if (bucket_iterator != bucket.end())
return Iterator(*this, false, bucket_iterator, bucket_index);
return end();
}
template<typename Finder>
ConstIterator find(unsigned hash, Finder finder) const
{
if (is_empty())
return end();
int bucket_index;
auto& bucket = lookup_with_hash(hash, &bucket_index);
auto bucket_iterator = bucket.find(finder);
if (bucket_iterator != bucket.end())
return ConstIterator(*this, false, bucket_iterator, bucket_index);
return end();
}
Iterator find(const T& value)
{
return find(TraitsForT::hash(value), [&](auto& other) { return TraitsForT::equals(value, other); });
}
ConstIterator find(const T& value) const
{
return find(TraitsForT::hash(value), [&](auto& other) { return TraitsForT::equals(value, other); });
}
void remove(const T& value)
{
@ -161,6 +195,21 @@ public:
private:
Bucket& lookup(const T&, int* bucket_index = nullptr);
const Bucket& lookup(const T&, int* bucket_index = nullptr) const;
Bucket& lookup_with_hash(unsigned hash, int* bucket_index)
{
if (bucket_index)
*bucket_index = hash % m_capacity;
return m_buckets[hash % m_capacity];
}
const Bucket& lookup_with_hash(unsigned hash, int* bucket_index) const
{
if (bucket_index)
*bucket_index = hash % m_capacity;
return m_buckets[hash % m_capacity];
}
void rehash(int capacity);
void insert(const T&);
void insert(T&&);
@ -273,32 +322,6 @@ bool HashTable<T, TraitsForT>::contains(const T& value) const
return false;
}
template<typename T, typename TraitsForT>
auto HashTable<T, TraitsForT>::find(const T& value) -> Iterator
{
if (is_empty())
return end();
int bucket_index;
auto& bucket = lookup(value, &bucket_index);
auto bucket_iterator = bucket.template find<TraitsForT>(value);
if (bucket_iterator != bucket.end())
return Iterator(*this, false, bucket_iterator, bucket_index);
return end();
}
template<typename T, typename TraitsForT>
auto HashTable<T, TraitsForT>::find(const T& value) const -> ConstIterator
{
if (is_empty())
return end();
int bucket_index;
const auto& bucket = lookup(value, &bucket_index);
auto bucket_iterator = bucket.template find<TraitsForT>(value);
if (bucket_iterator != bucket.end())
return ConstIterator(*this, false, bucket_iterator, bucket_index);
return end();
}
template<typename T, typename TraitsForT>
void HashTable<T, TraitsForT>::remove(Iterator it)
{