11 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
13 : _hash(hash), _equal(equal), _blank(blank), _size(0), _buckets(allocator)
18 _buckets.resize(
reserve, std::make_pair(_blank, TValue()));
21 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
22 template <
class InputIterator>
23 inline HashMap<TKey, TValue, THash, TEqual, TAllocator>::HashMap(InputIterator first, InputIterator last,
bool unused,
size_t capacity,
const TKey& blank,
const THash& hash,
const TEqual& equal,
const TAllocator& allocator)
24 :
HashMap(capacity, blank, hash, equal, allocator)
26 for (
auto it = first; it != last; ++it)
30 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
32 :
HashMap(hashmap.bucket_count(), hashmap._blank, hashmap._hash, hashmap._equal, hashmap._buckets.get_allocator())
34 for (
const auto& item : hashmap)
38 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
40 :
HashMap(capacity, hashmap._blank, hashmap._hash, hashmap._equal, hashmap._buckets.get_allocator())
42 for (
const auto& item : hashmap)
46 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
50 reserve(hashmap.
size());
51 for (
const auto& item : hashmap)
56 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
62 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
68 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
74 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
80 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
86 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
92 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
98 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
104 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
110 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
116 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
122 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
128 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
131 assert(!key_equal(key, _blank) &&
"Cannot find a blank key!");
133 for (
size_t index = key_to_index(key);; index = next_index(index))
135 if (key_equal(_buckets[index].first, key))
137 if (key_equal(_buckets[index].first, _blank))
142 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
145 assert(!key_equal(key, _blank) &&
"Cannot find a blank key!");
147 for (
size_t index = key_to_index(key);; index = next_index(index))
149 if (key_equal(_buckets[index].first, key))
151 if (key_equal(_buckets[index].first, _blank))
156 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
157 inline std::pair<typename HashMap<TKey, TValue, THash, TEqual, TAllocator>::iterator,
typename HashMap<TKey, TValue, THash, TEqual, TAllocator>::iterator>
HashMap<TKey, TValue, THash, TEqual, TAllocator>::equal_range(
const TKey& key) noexcept
159 return std::make_pair(find(key), end());
162 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
163 inline std::pair<typename HashMap<TKey, TValue, THash, TEqual, TAllocator>::const_iterator,
typename HashMap<TKey, TValue, THash, TEqual, TAllocator>::const_iterator>
HashMap<TKey, TValue, THash, TEqual, TAllocator>::equal_range(
const TKey& key)
const noexcept
165 return std::make_pair(find(key), end());
168 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
173 throw std::out_of_range(
"Item with the given key was not found in the hash map!");
178 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
183 throw std::out_of_range(
"Item with the given key was not found in the hash map!");
188 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
191 return emplace_internal(item.first, item.second);
194 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
197 return emplace_internal(item.first, std::move(item.second));
200 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
201 template <
typename... Args>
204 return emplace_internal(std::forward<Args>(args)...);
207 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
214 erase_internal(it._index);
218 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
221 erase_internal(position._index);
224 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
225 template <
typename... Args>
226 inline std::pair<typename HashMap<TKey, TValue, THash, TEqual, TAllocator>::iterator,
bool>
HashMap<TKey, TValue, THash, TEqual, TAllocator>::emplace_internal(
const TKey& key, Args&&... args)
228 assert(!key_equal(key, _blank) &&
"Cannot emplace a blank key!");
232 for (
size_t index = key_to_index(key);; index = next_index(index))
234 if (key_equal(_buckets[index].first, key))
235 return std::make_pair(
iterator(
this, index),
false);
236 if (key_equal(_buckets[index].first, _blank))
238 _buckets[index].first = key;
239 _buckets[index].second = TValue(std::forward<Args>(args)...);
241 return std::make_pair(
iterator(
this, index),
true);
246 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
249 size_t current = index;
250 for (index = next_index(current);; index = next_index(index))
252 if (key_equal(_buckets[index].first, _blank))
254 _buckets[current].first = _blank;
260 size_t base = key_to_index(_buckets[index].first);
261 if (diff(current, base) < diff(index, base))
263 _buckets[current] = _buckets[index];
269 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
270 inline size_t HashMap<TKey, TValue, THash, TEqual, TAllocator>::key_to_index(
const TKey& key)
const noexcept
272 size_t mask = _buckets.size() - 1;
273 return _hash(key) & mask;
276 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
277 inline size_t HashMap<TKey, TValue, THash, TEqual, TAllocator>::next_index(
size_t index)
const noexcept
279 size_t mask = _buckets.size() - 1;
280 return (index + 1) & mask;
283 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
284 inline size_t HashMap<TKey, TValue, THash, TEqual, TAllocator>::diff(
size_t index1,
size_t index2)
const noexcept
286 size_t mask = _buckets.size() - 1;
287 return (_buckets.size() + (index1 - index2)) & mask;
290 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
293 capacity = std::max(capacity, 2 * size());
298 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
301 if (_buckets.size() < 2 * count)
305 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
309 for (
auto& bucket : _buckets)
310 bucket.first = _blank;
313 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
317 swap(_hash, hashmap._hash);
318 swap(_equal, hashmap._equal);
319 swap(_blank, hashmap._blank);
320 swap(_size, hashmap._size);
321 swap(_buckets, hashmap._buckets);
324 template <
typename TKey,
typename TValue,
typename THash,
typename TEqual,
typename TAllocator>
327 hashmap1.swap(hashmap2);
330 template <
class TContainer,
typename TKey,
typename TValue>
333 if (_container !=
nullptr)
335 if (_container->size() == 0)
338 _container =
nullptr;
344 for (
size_t i = 0; i < _container->_buckets.size(); ++i)
346 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
353 assert(
false &&
"Non empty hash map has no valid items!");
358 template <
class TContainer,
typename TKey,
typename TValue>
361 if (_container !=
nullptr)
363 for (
size_t i = _index + 1; i < _container->_buckets.size(); ++i)
365 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
373 _container =
nullptr;
380 template <
class TContainer,
typename TKey,
typename TValue>
388 template <
class TContainer,
typename TKey,
typename TValue>
391 assert(((_container !=
nullptr) && (_index < _container->_buckets.size())) &&
"Iterator must be valid!");
393 return _container->_buckets[_index];
396 template <
class TContainer,
typename TKey,
typename TValue>
399 return ((_container !=
nullptr) && (_index < _container->_buckets.size())) ? &_container->_buckets[_index] :
nullptr;
402 template <
class TContainer,
typename TKey,
typename TValue>
406 swap(_container, it._container);
407 swap(_index, it._index);
410 template <
class TContainer,
typename TKey,
typename TValue>
416 template <
class TContainer,
typename TKey,
typename TValue>
419 if (_container !=
nullptr)
421 if (_container->size() == 0)
424 _container =
nullptr;
430 for (
size_t i = 0; i < _container->_buckets.size(); ++i)
432 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
439 assert(
false &&
"Non empty hash map has no valid items!");
444 template <
class TContainer,
typename TKey,
typename TValue>
447 if (_container !=
nullptr)
449 for (
size_t i = _index + 1; i < _container->_buckets.size(); ++i)
451 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
459 _container =
nullptr;
466 template <
class TContainer,
typename TKey,
typename TValue>
474 template <
class TContainer,
typename TKey,
typename TValue>
477 assert(((_container !=
nullptr) && (_index < _container->_buckets.size())) &&
"Iterator must be valid!");
479 return _container->_buckets[_index];
482 template <
class TContainer,
typename TKey,
typename TValue>
485 return ((_container !=
nullptr) && (_index < _container->_buckets.size())) ? &_container->_buckets[_index] :
nullptr;
488 template <
class TContainer,
typename TKey,
typename TValue>
492 swap(_container, it._container);
493 swap(_index, it._index);
496 template <
class TContainer,
typename TKey,
typename TValue>
502 template <
class TContainer,
typename TKey,
typename TValue>
505 if (_container !=
nullptr)
507 if (_container->size() == 0)
510 _container =
nullptr;
516 for (
size_t i = _container->_buckets.size(); i-- > 0;)
518 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
525 assert(
false &&
"Non empty hash map has no valid items!");
530 template <
class TContainer,
typename TKey,
typename TValue>
533 if (_container !=
nullptr)
535 for (
size_t i = _index; i-- > 0;)
537 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
545 _container =
nullptr;
552 template <
class TContainer,
typename TKey,
typename TValue>
560 template <
class TContainer,
typename TKey,
typename TValue>
563 assert(((_container !=
nullptr) && (_index < _container->_buckets.size())) &&
"Iterator must be valid!");
565 return _container->_buckets[_index];
568 template <
class TContainer,
typename TKey,
typename TValue>
571 return ((_container !=
nullptr) && (_index < _container->_buckets.size())) ? &_container->_buckets[_index] :
nullptr;
574 template <
class TContainer,
typename TKey,
typename TValue>
578 swap(_container, it._container);
579 swap(_index, it._index);
582 template <
class TContainer,
typename TKey,
typename TValue>
588 template <
class TContainer,
typename TKey,
typename TValue>
591 if (_container !=
nullptr)
593 if (_container->size() == 0)
596 _container =
nullptr;
602 for (
size_t i = _container->_buckets.size(); i-- > 0;)
604 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
611 assert(
false &&
"Non empty hash map has no valid items!");
616 template <
class TContainer,
typename TKey,
typename TValue>
619 if (_container !=
nullptr)
621 for (
size_t i = _index; i-- > 0;)
623 if (!_container->key_equal(_container->_buckets[i].first, _container->_blank))
631 _container =
nullptr;
638 template <
class TContainer,
typename TKey,
typename TValue>
646 template <
class TContainer,
typename TKey,
typename TValue>
649 assert(((_container !=
nullptr) && (_index < _container->_buckets.size())) &&
"Iterator must be valid!");
651 return _container->_buckets[_index];
654 template <
class TContainer,
typename TKey,
typename TValue>
657 return ((_container !=
nullptr) && (_index < _container->_buckets.size())) ? &_container->_buckets[_index] :
nullptr;
660 template <
class TContainer,
typename TKey,
typename TValue>
664 swap(_container, it._container);
665 swap(_index, it._index);
668 template <
class TContainer,
typename TKey,
typename TValue>
Hash map constant iterator.
HashMapConstIterator() noexcept
const_reference operator*() const noexcept
void swap(HashMapConstIterator &it) noexcept
Swap two instances.
HashMapConstIterator & operator++() noexcept
const value_type * const_pointer
const_pointer operator->() const noexcept
const value_type & const_reference
Hash map constant reverse iterator.
const_reference operator*() const noexcept
void swap(HashMapConstReverseIterator &it) noexcept
Swap two instances.
HashMapConstReverseIterator() noexcept
const_pointer operator->() const noexcept
HashMapConstReverseIterator & operator++() noexcept
const value_type & const_reference
const value_type * const_pointer
iterator find(const TKey &key) noexcept
Find the iterator which points to the first item with the given key in the hash map or return end ite...
reverse_iterator rbegin() noexcept
Get the reverse begin hash map iterator.
std::pair< iterator, bool > insert(const value_type &item)
Insert a new item into the hash map.
void clear() noexcept
Clear the hash map.
mapped_type & at(const TKey &key) noexcept
Access to the item with the given key or throw std::out_of_range exception.
const_iterator cend() const noexcept
const_iterator cbegin() const noexcept
void rehash(size_t capacity)
Rehash the hash map to the given capacity or more.
std::pair< iterator, bool > emplace(Args &&... args)
Emplace a new item into the hash map.
const_reverse_iterator crend() const noexcept
const_reverse_iterator crbegin() const noexcept
void reserve(size_t count)
Reserve the hash map capacity to fit the given count of items.
iterator end() noexcept
Get the end hash map iterator.
HashMap(size_t capacity=128, const TKey &blank=TKey(), const THash &hash=THash(), const TEqual &equal=TEqual(), const TAllocator &allocator=TAllocator())
Initialize the hash map with a given capacity and blank key value.
std::pair< TKey, TValue > value_type
HashMap & operator=(const HashMap &hashmap)
size_t size() const noexcept
Get the hash map size.
reverse_iterator rend() noexcept
Get the reverse end hash map iterator.
void swap(HashMap &hashmap) noexcept
Swap two instances.
size_t erase(const TKey &key)
Erase the item with the given key from the hash map.
std::pair< iterator, iterator > equal_range(const TKey &key) noexcept
Find the bounds of a range that includes all the elements in the hash map with the given key.
iterator begin() noexcept
Get the begin hash map iterator.
void swap(HashMapIterator &it) noexcept
Swap two instances.
HashMapIterator() noexcept
pointer operator->() noexcept
HashMapIterator & operator++() noexcept
reference operator*() noexcept
Hash map reverse iterator.
reference operator*() noexcept
HashMapReverseIterator & operator++() noexcept
HashMapReverseIterator() noexcept
pointer operator->() noexcept
void swap(HashMapReverseIterator &it) noexcept
Swap two instances.
C++ Common project definitions.
void swap(HashMapConstReverseIterator< TContainer, TKey, TValue > &it1, HashMapConstReverseIterator< TContainer, TKey, TValue > &it2) noexcept
void swap(FileCache &cache1, FileCache &cache2) noexcept