CppCommon  1.0.4.1
C++ Common Library
hashmap.h
Go to the documentation of this file.
1 
9 #ifndef CPPCOMMON_CONTAINERS_HASHMAP_H
10 #define CPPCOMMON_CONTAINERS_HASHMAP_H
11 
12 #include <algorithm>
13 #include <cassert>
14 #include <cstddef>
15 #include <functional>
16 #include <iterator>
17 #include <limits>
18 #include <stdexcept>
19 #include <vector>
20 
21 namespace CppCommon {
22 
23 template <class TContainer, typename TKey, typename TValue>
24 class HashMapIterator;
25 template <class TContainer, typename TKey, typename TValue>
27 template <class TContainer, typename TKey, typename TValue>
29 template <class TContainer, typename TKey, typename TValue>
31 
33 
43 template <typename TKey, typename TValue, typename THash = std::hash<TKey>, typename TEqual = std::equal_to<TKey>, typename TAllocator = std::allocator<std::pair<TKey, TValue>>>
44 class HashMap
45 {
46  friend class HashMapIterator<HashMap<TKey, TValue, THash, TEqual, TAllocator>, TKey, TValue>;
47  friend class HashMapConstIterator<HashMap<TKey, TValue, THash, TEqual, TAllocator>, TKey, TValue>;
48  friend class HashMapReverseIterator<HashMap<TKey, TValue, THash, TEqual, TAllocator>, TKey, TValue>;
49  friend class HashMapConstReverseIterator<HashMap<TKey, TValue, THash, TEqual, TAllocator>, TKey, TValue>;
50 
51 public:
52  // Standard container type definitions
53  typedef TKey key_type;
54  typedef TValue mapped_type;
55  typedef std::pair<TKey, TValue> value_type;
57  typedef const value_type& const_reference;
58  typedef value_type* pointer;
59  typedef const value_type* const_pointer;
60  typedef ptrdiff_t difference_type;
61  typedef size_t size_type;
66 
68 
75  explicit HashMap(size_t capacity = 128, const TKey& blank = TKey(), const THash& hash = THash(), const TEqual& equal = TEqual(), const TAllocator& allocator = TAllocator());
76  template <class InputIterator>
77  HashMap(InputIterator first, InputIterator last, bool unused, size_t capacity = 128, const TKey& blank = TKey(), const THash& hash = THash(), const TEqual& equal = TEqual(), const TAllocator& allocator = TAllocator());
78  HashMap(const HashMap& hashmap);
79  HashMap(const HashMap& hashmap, size_t capacity);
80  HashMap(HashMap&&) = default;
81  ~HashMap() = default;
82 
83  HashMap& operator=(const HashMap& hashmap);
84  HashMap& operator=(HashMap&&) = default;
85 
87  explicit operator bool() const noexcept { return !empty(); }
88 
90  mapped_type& operator[](const TKey& key) { return emplace_internal(key).first->second; }
91 
93  bool empty() const noexcept { return _size == 0; }
94 
96  size_t size() const noexcept { return _size; }
98  size_t max_size() const noexcept { return std::numeric_limits<size_type>::max(); }
100  size_t bucket_count() const noexcept { return _buckets.size(); }
102  size_t max_bucket_count() const noexcept { return std::numeric_limits<size_type>::max(); }
103 
105  size_t key_hash(const TKey& key) const noexcept { return _hash(key); }
107  bool key_equal(const TKey& key1, const TKey& key2) const noexcept { return _equal(key1, key2); }
108 
110  iterator begin() noexcept;
111  const_iterator begin() const noexcept;
112  const_iterator cbegin() const noexcept;
114  iterator end() noexcept;
115  const_iterator end() const noexcept;
116  const_iterator cend() const noexcept;
117 
119  reverse_iterator rbegin() noexcept;
120  const_reverse_iterator rbegin() const noexcept;
121  const_reverse_iterator crbegin() const noexcept;
123  reverse_iterator rend() noexcept;
124  const_reverse_iterator rend() const noexcept;
125  const_reverse_iterator crend() const noexcept;
126 
128  iterator find(const TKey& key) noexcept;
129  const_iterator find(const TKey& key) const noexcept;
130 
132  std::pair<iterator, iterator> equal_range(const TKey& key) noexcept;
133  std::pair<const_iterator, const_iterator> equal_range(const TKey& key) const noexcept;
134 
136  size_t count(const TKey& key) const noexcept { return (find(key) == end()) ? 0 : 1; }
137 
139 
143  mapped_type& at(const TKey& key) noexcept;
145 
149  const mapped_type& at(const TKey& key) const noexcept;
150 
152 
156  std::pair<iterator, bool> insert(const value_type& item);
158 
162  std::pair<iterator, bool> insert(value_type&& item);
163 
165 
169  template <typename... Args>
170  std::pair<iterator, bool> emplace(Args&&... args);
171 
173 
177  size_t erase(const TKey& key);
179 
182  void erase(const const_iterator& position);
183 
185 
188  void rehash(size_t capacity);
190 
193  void reserve(size_t count);
194 
196  void clear() noexcept;
197 
199  void swap(HashMap& hashmap) noexcept;
200  template <typename UKey, typename UValue, typename UHash, typename UEqual, typename UAllocator>
201  friend void swap(HashMap<UKey, UValue, UHash, UEqual, UAllocator>& hashmap1, HashMap<UKey, UValue, UHash, UEqual, UAllocator>& hashmap2) noexcept;
202 
203 private:
204  THash _hash; // Hash map key hasher
205  TEqual _equal; // Hash map key comparator
206  TKey _blank; // Hash map blank key
207  size_t _size; // Hash map size
208  std::vector<value_type, TAllocator> _buckets; // Hash map buckets
209 
210  template <typename... Args>
211  std::pair<iterator, bool> emplace_internal(const TKey& key, Args&&... args);
212  void erase_internal(size_t index);
213  size_t key_to_index(const TKey& key) const noexcept;
214  size_t next_index(size_t index) const noexcept;
215  size_t diff(size_t index1, size_t index2) const noexcept;
216 };
217 
219 
222 template <class TContainer, typename TKey, typename TValue>
224 {
226  friend TContainer;
227 
228 public:
229  // Standard iterator type definitions
230  typedef std::pair<TKey, TValue> value_type;
232  typedef const value_type& const_reference;
233  typedef value_type* pointer;
234  typedef const value_type* const_pointer;
235  typedef ptrdiff_t difference_type;
236  typedef size_t size_type;
237  typedef std::bidirectional_iterator_tag iterator_category;
238 
239  HashMapIterator() noexcept : _container(nullptr), _index(0) {}
240  explicit HashMapIterator(TContainer* container) noexcept;
241  explicit HashMapIterator(TContainer* container, size_t index) noexcept : _container(container), _index(index) {}
242  HashMapIterator(const HashMapIterator& it) noexcept = default;
243  HashMapIterator(HashMapIterator&& it) noexcept = default;
244  ~HashMapIterator() noexcept = default;
245 
246  HashMapIterator& operator=(const HashMapIterator& it) noexcept = default;
247  HashMapIterator& operator=(HashMapIterator&& it) noexcept = default;
248 
249  friend bool operator==(const HashMapIterator& it1, const HashMapIterator& it2) noexcept
250  { return (it1._container == it2._container) && (it1._index == it2._index); }
251  friend bool operator!=(const HashMapIterator& it1, const HashMapIterator& it2) noexcept
252  { return (it1._container != it2._container) || (it1._index != it2._index); }
253 
254  HashMapIterator& operator++() noexcept;
255  HashMapIterator operator++(int) noexcept;
256 
257  reference operator*() noexcept;
258  pointer operator->() noexcept;
259 
261  explicit operator bool() const noexcept { return _container != nullptr; }
262 
264  void swap(HashMapIterator& it) noexcept;
265  template <class UContainer, typename UKey, typename UValue>
267 
268 private:
269  TContainer* _container;
270  size_t _index;
271 };
272 
274 
277 template <class TContainer, typename TKey, typename TValue>
279 {
280  friend TContainer;
281 
282 public:
283  // Standard iterator type definitions
284  typedef std::pair<TKey, TValue> value_type;
286  typedef const value_type& const_reference;
287  typedef value_type* pointer;
288  typedef const value_type* const_pointer;
289  typedef ptrdiff_t difference_type;
290  typedef size_t size_type;
291  typedef std::bidirectional_iterator_tag iterator_category;
292 
293  HashMapConstIterator() noexcept : _container(nullptr), _index(0) {}
294  explicit HashMapConstIterator(const TContainer* container) noexcept;
295  explicit HashMapConstIterator(const TContainer* container, size_t index) noexcept : _container(container), _index(index) {}
296  HashMapConstIterator(const HashMapIterator<TContainer, TKey, TValue>& it) noexcept : _container(it._container), _index(it._index) {}
297  HashMapConstIterator(const HashMapConstIterator& it) noexcept = default;
298  HashMapConstIterator(HashMapConstIterator&& it) noexcept = default;
299  ~HashMapConstIterator() noexcept = default;
300 
301  HashMapConstIterator& operator=(const HashMapIterator<TContainer, TKey, TValue>& it) noexcept
302  { _container = it._container; _index = it._index; return *this; }
303  HashMapConstIterator& operator=(const HashMapConstIterator& it) noexcept = default;
305 
306  friend bool operator==(const HashMapConstIterator& it1, const HashMapConstIterator& it2) noexcept
307  { return (it1._container == it2._container) && (it1._index == it2._index); }
308  friend bool operator!=(const HashMapConstIterator& it1, const HashMapConstIterator& it2) noexcept
309  { return (it1._container != it2._container) || (it1._index != it2._index); }
310 
311  HashMapConstIterator& operator++() noexcept;
312  HashMapConstIterator operator++(int) noexcept;
313 
314  const_reference operator*() const noexcept;
315  const_pointer operator->() const noexcept;
316 
318  explicit operator bool() const noexcept { return _container != nullptr; }
319 
321  void swap(HashMapConstIterator& it) noexcept;
322  template <class UContainer, typename UKey, typename UValue>
324 
325 private:
326  const TContainer* _container;
327  size_t _index;
328 };
329 
331 
334 template <class TContainer, typename TKey, typename TValue>
336 {
338  friend TContainer;
339 
340 public:
341  // Standard iterator type definitions
342  typedef std::pair<TKey, TValue> value_type;
344  typedef const value_type& const_reference;
345  typedef value_type* pointer;
346  typedef const value_type* const_pointer;
347  typedef ptrdiff_t difference_type;
348  typedef size_t size_type;
349  typedef std::bidirectional_iterator_tag iterator_category;
350 
351  HashMapReverseIterator() noexcept : _container(nullptr), _index(0) {}
352  explicit HashMapReverseIterator(TContainer* container) noexcept;
353  explicit HashMapReverseIterator(TContainer* container, size_t index) noexcept : _container(container), _index(index) {}
354  HashMapReverseIterator(const HashMapReverseIterator& it) noexcept = default;
356  ~HashMapReverseIterator() noexcept = default;
357 
358  HashMapReverseIterator& operator=(const HashMapReverseIterator& it) noexcept = default;
359  HashMapReverseIterator& operator=(HashMapReverseIterator&& it) noexcept = default;
360 
361  friend bool operator==(const HashMapReverseIterator& it1, const HashMapReverseIterator& it2) noexcept
362  { return (it1._container == it2._container) && (it1._index == it2._index); }
363  friend bool operator!=(const HashMapReverseIterator& it1, const HashMapReverseIterator& it2) noexcept
364  { return (it1._container != it2._container) || (it1._index != it2._index); }
365 
366  HashMapReverseIterator& operator++() noexcept;
367  HashMapReverseIterator operator++(int) noexcept;
368 
369  reference operator*() noexcept;
370  pointer operator->() noexcept;
371 
373  explicit operator bool() const noexcept { return _container != nullptr; }
374 
376  void swap(HashMapReverseIterator& it) noexcept;
377  template <class UContainer, typename UKey, typename UValue>
379 
380 private:
381  TContainer* _container;
382  size_t _index;
383 };
384 
386 
389 template <class TContainer, typename TKey, typename TValue>
391 {
392  friend TContainer;
393 
394 public:
395  // Standard iterator type definitions
396  typedef std::pair<TKey, TValue> value_type;
398  typedef const value_type& const_reference;
399  typedef value_type* pointer;
400  typedef const value_type* const_pointer;
401  typedef ptrdiff_t difference_type;
402  typedef size_t size_type;
403  typedef std::bidirectional_iterator_tag iterator_category;
404 
405  HashMapConstReverseIterator() noexcept : _container(nullptr), _index(0) {}
406  explicit HashMapConstReverseIterator(const TContainer* container) noexcept;
407  explicit HashMapConstReverseIterator(const TContainer* container, size_t index) noexcept : _container(container), _index(index) {}
408  HashMapConstReverseIterator(const HashMapReverseIterator<TContainer, TKey, TValue>& it) noexcept : _container(it._container), _index(it._index) {}
411  ~HashMapConstReverseIterator() noexcept = default;
412 
413  HashMapConstReverseIterator& operator=(const HashMapReverseIterator<TContainer, TKey, TValue>& it) noexcept
414  { _container = it._container; _index = it._index; return *this; }
417 
418  friend bool operator==(const HashMapConstReverseIterator& it1, const HashMapConstReverseIterator& it2) noexcept
419  { return (it1._container == it2._container) && (it1._index == it2._index); }
420  friend bool operator!=(const HashMapConstReverseIterator& it1, const HashMapConstReverseIterator& it2) noexcept
421  { return (it1._container != it2._container) || (it1._index != it2._index); }
422 
423  HashMapConstReverseIterator& operator++() noexcept;
424  HashMapConstReverseIterator operator++(int) noexcept;
425 
426  const_reference operator*() const noexcept;
427  const_pointer operator->() const noexcept;
428 
430  explicit operator bool() const noexcept { return _container != nullptr; }
431 
433  void swap(HashMapConstReverseIterator& it) noexcept;
434  template <class UContainer, typename UKey, typename UValue>
436 
437 private:
438  const TContainer* _container;
439  size_t _index;
440 };
441 
444 } // namespace CppCommon
445 
446 #include "hashmap.inl"
447 
448 #endif // CPPCOMMON_CONTAINERS_HASHMAP_H
Hash map constant iterator.
Definition: hashmap.h:279
HashMapConstIterator(HashMapConstIterator &&it) noexcept=default
HashMapConstIterator(const HashMapConstIterator &it) noexcept=default
friend void swap(HashMapConstIterator< UContainer, UKey, UValue > &it1, HashMapConstIterator< UContainer, UKey, UValue > &it2) noexcept
HashMapConstIterator & operator=(HashMapConstIterator &&it) noexcept=default
HashMapConstIterator(const HashMapIterator< TContainer, TKey, TValue > &it) noexcept
Definition: hashmap.h:296
std::pair< TKey, TValue > value_type
Definition: hashmap.h:284
friend bool operator==(const HashMapConstIterator &it1, const HashMapConstIterator &it2) noexcept
Definition: hashmap.h:306
const value_type * const_pointer
Definition: hashmap.h:288
friend bool operator!=(const HashMapConstIterator &it1, const HashMapConstIterator &it2) noexcept
Definition: hashmap.h:308
std::bidirectional_iterator_tag iterator_category
Definition: hashmap.h:291
HashMapConstIterator(const TContainer *container, size_t index) noexcept
Definition: hashmap.h:295
HashMapConstIterator & operator=(const HashMapConstIterator &it) noexcept=default
~HashMapConstIterator() noexcept=default
const value_type & const_reference
Definition: hashmap.h:286
Hash map constant reverse iterator.
Definition: hashmap.h:391
HashMapConstReverseIterator(HashMapConstReverseIterator &&it) noexcept=default
friend void swap(HashMapConstReverseIterator< UContainer, UKey, UValue > &it1, HashMapConstReverseIterator< UContainer, UKey, UValue > &it2) noexcept
~HashMapConstReverseIterator() noexcept=default
HashMapConstReverseIterator & operator=(const HashMapConstReverseIterator &it) noexcept=default
friend bool operator!=(const HashMapConstReverseIterator &it1, const HashMapConstReverseIterator &it2) noexcept
Definition: hashmap.h:420
HashMapConstReverseIterator(const TContainer *container, size_t index) noexcept
Definition: hashmap.h:407
const value_type & const_reference
Definition: hashmap.h:398
HashMapConstReverseIterator & operator=(HashMapConstReverseIterator &&it) noexcept=default
HashMapConstReverseIterator(const HashMapConstReverseIterator &it) noexcept=default
std::bidirectional_iterator_tag iterator_category
Definition: hashmap.h:403
const value_type * const_pointer
Definition: hashmap.h:400
HashMapConstReverseIterator(const HashMapReverseIterator< TContainer, TKey, TValue > &it) noexcept
Definition: hashmap.h:408
std::pair< TKey, TValue > value_type
Definition: hashmap.h:396
friend bool operator==(const HashMapConstReverseIterator &it1, const HashMapConstReverseIterator &it2) noexcept
Definition: hashmap.h:418
Hash map container.
Definition: hashmap.h:45
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...
Definition: hashmap.inl:129
HashMapReverseIterator< HashMap< TKey, TValue, THash, TEqual, TAllocator >, TKey, TValue > reverse_iterator
Definition: hashmap.h:64
HashMapConstReverseIterator< HashMap< TKey, TValue, THash, TEqual, TAllocator >, TKey, TValue > const_reverse_iterator
Definition: hashmap.h:65
const value_type * const_pointer
Definition: hashmap.h:59
reverse_iterator rbegin() noexcept
Get the reverse begin hash map iterator.
Definition: hashmap.inl:93
ptrdiff_t difference_type
Definition: hashmap.h:60
value_type & reference
Definition: hashmap.h:56
std::pair< iterator, bool > insert(const value_type &item)
Insert a new item into the hash map.
Definition: hashmap.inl:189
TValue mapped_type
Definition: hashmap.h:54
HashMap & operator=(HashMap &&)=default
void clear() noexcept
Clear the hash map.
Definition: hashmap.inl:306
mapped_type & at(const TKey &key) noexcept
Access to the item with the given key or throw std::out_of_range exception.
Definition: hashmap.inl:169
const_iterator cend() const noexcept
Definition: hashmap.inl:87
const_iterator cbegin() const noexcept
Definition: hashmap.inl:69
void rehash(size_t capacity)
Rehash the hash map to the given capacity or more.
Definition: hashmap.inl:291
size_t count(const TKey &key) const noexcept
Find the count of items with the given key.
Definition: hashmap.h:136
HashMapConstIterator< HashMap< TKey, TValue, THash, TEqual, TAllocator >, TKey, TValue > const_iterator
Definition: hashmap.h:63
std::pair< iterator, bool > emplace(Args &&... args)
Emplace a new item into the hash map.
size_t size_type
Definition: hashmap.h:61
const_reverse_iterator crend() const noexcept
Definition: hashmap.inl:123
const_reverse_iterator crbegin() const noexcept
Definition: hashmap.inl:105
void reserve(size_t count)
Reserve the hash map capacity to fit the given count of items.
Definition: hashmap.inl:299
value_type * pointer
Definition: hashmap.h:58
iterator end() noexcept
Get the end hash map iterator.
Definition: hashmap.inl:75
bool key_equal(const TKey &key1, const TKey &key2) const noexcept
Compare two keys: if the first key equals to the second one?
Definition: hashmap.h:107
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.
Definition: hashmap.inl:12
size_t max_size() const noexcept
Get the hash map maximum size.
Definition: hashmap.h:98
std::pair< TKey, TValue > value_type
Definition: hashmap.h:55
HashMap & operator=(const HashMap &hashmap)
Definition: hashmap.inl:47
bool empty() const noexcept
Is the hash map empty?
Definition: hashmap.h:93
HashMap(HashMap &&)=default
const value_type & const_reference
Definition: hashmap.h:57
mapped_type & operator[](const TKey &key)
Access to the item with the given key or insert a new one.
Definition: hashmap.h:90
size_t size() const noexcept
Get the hash map size.
Definition: hashmap.h:96
reverse_iterator rend() noexcept
Get the reverse end hash map iterator.
Definition: hashmap.inl:111
void swap(HashMap &hashmap) noexcept
Swap two instances.
Definition: hashmap.inl:314
size_t erase(const TKey &key)
Erase the item with the given key from the hash map.
Definition: hashmap.inl:208
size_t key_hash(const TKey &key) const noexcept
Calculate hash of the given key.
Definition: hashmap.h:105
HashMapIterator< HashMap< TKey, TValue, THash, TEqual, TAllocator >, TKey, TValue > iterator
Definition: hashmap.h:62
size_t max_bucket_count() const noexcept
Get the hash map maximum bucket count.
Definition: hashmap.h:102
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.
Definition: hashmap.inl:157
iterator begin() noexcept
Get the begin hash map iterator.
Definition: hashmap.inl:57
size_t bucket_count() const noexcept
Get the hash map bucket count.
Definition: hashmap.h:100
Hash map iterator.
Definition: hashmap.h:224
HashMapIterator() noexcept
Definition: hashmap.h:239
friend void swap(HashMapIterator< UContainer, UKey, UValue > &it1, HashMapIterator< UContainer, UKey, UValue > &it2) noexcept
value_type * pointer
Definition: hashmap.h:233
~HashMapIterator() noexcept=default
HashMapIterator(HashMapIterator &&it) noexcept=default
std::pair< TKey, TValue > value_type
Definition: hashmap.h:230
const value_type & const_reference
Definition: hashmap.h:232
HashMapIterator(const HashMapIterator &it) noexcept=default
friend bool operator!=(const HashMapIterator &it1, const HashMapIterator &it2) noexcept
Definition: hashmap.h:251
std::bidirectional_iterator_tag iterator_category
Definition: hashmap.h:237
value_type & reference
Definition: hashmap.h:231
HashMapIterator(TContainer *container, size_t index) noexcept
Definition: hashmap.h:241
const value_type * const_pointer
Definition: hashmap.h:234
Hash map reverse iterator.
Definition: hashmap.h:336
~HashMapReverseIterator() noexcept=default
const value_type * const_pointer
Definition: hashmap.h:346
std::pair< TKey, TValue > value_type
Definition: hashmap.h:342
HashMapReverseIterator(const HashMapReverseIterator &it) noexcept=default
const value_type & const_reference
Definition: hashmap.h:344
std::bidirectional_iterator_tag iterator_category
Definition: hashmap.h:349
HashMapReverseIterator(TContainer *container, size_t index) noexcept
Definition: hashmap.h:353
friend bool operator!=(const HashMapReverseIterator &it1, const HashMapReverseIterator &it2) noexcept
Definition: hashmap.h:363
friend void swap(HashMapReverseIterator< UContainer, UKey, UValue > &it1, HashMapReverseIterator< UContainer, UKey, UValue > &it2) noexcept
HashMapReverseIterator(HashMapReverseIterator &&it) noexcept=default
Hash map container inline implementation.
C++ Common project definitions.
Definition: token_bucket.h:15