IOSS 2.0
Loading...
Searching...
No Matches
hopscotch_map.h
Go to the documentation of this file.
1/**
2 * MIT License
3 *
4 * Copyright (c) 2017 Thibaut Goetghebuer-Planchon <tessil@gmx.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef TSL_HOPSCOTCH_MAP_H
25#define TSL_HOPSCOTCH_MAP_H
26
27#include <algorithm>
28#include <cstddef>
29#include <functional>
30#include <initializer_list>
31#include <list>
32#include <memory>
33#include <type_traits>
34#include <utility>
35
36#include "hopscotch_hash.h"
37
38namespace tsl {
39
40 /**
41 * Implementation of a hash map using the hopscotch hashing algorithm.
42 *
43 * The Key and the value T must be either nothrow move-constructible,
44 * copy-constructible or both.
45 *
46 * The size of the neighborhood (NeighborhoodSize) must be > 0 and <= 62 if
47 * StoreHash is false. When StoreHash is true, 32-bits of the hash will be
48 * stored alongside the neighborhood limiting the NeighborhoodSize to <= 30.
49 * There is no memory usage difference between 'NeighborhoodSize 62; StoreHash
50 * false' and 'NeighborhoodSize 30; StoreHash true'.
51 *
52 * Storing the hash may improve performance on insert during the rehash process
53 * if the hash takes time to compute. It may also improve read performance if
54 * the KeyEqual function takes time (or incurs a cache-miss). If used with
55 * simple Hash and KeyEqual it may slow things down.
56 *
57 * StoreHash can only be set if the GrowthPolicy is set to
58 * tsl::power_of_two_growth_policy.
59 *
60 * GrowthPolicy defines how the map grows and consequently how a hash value is
61 * mapped to a bucket. By default the map uses tsl::power_of_two_growth_policy.
62 * This policy keeps the number of buckets to a power of two and uses a mask to
63 * map the hash to a bucket instead of the slow modulo. You may define your own
64 * growth policy, check tsl::power_of_two_growth_policy for the interface.
65 *
66 * If the destructors of Key or T throw an exception, behaviour of the class is
67 * undefined.
68 *
69 * Iterators invalidation:
70 * - clear, operator=, reserve, rehash: always invalidate the iterators.
71 * - insert, emplace, emplace_hint, operator[]: if there is an effective
72 * insert, invalidate the iterators if a displacement is needed to resolve a
73 * collision (which mean that most of the time, insert will invalidate the
74 * iterators). Or if there is a rehash.
75 * - erase: iterator on the erased element is the only one which become
76 * invalid.
77 */
78 template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
79 class Allocator = std::allocator<std::pair<Key, T>>, unsigned int NeighborhoodSize = 62,
80 bool StoreHash = false, class GrowthPolicy = tsl::hh::power_of_two_growth_policy<2>>
82 {
83 private:
84 template <typename U>
86
88 {
89 public:
90 using key_type = Key;
91
92 const key_type &operator()(const std::pair<Key, T> &key_value) const
93 {
94 return key_value.first;
95 }
96
97 key_type &operator()(std::pair<Key, T> &key_value) { return key_value.first; }
98 };
99
101 {
102 public:
103 using value_type = T;
104
105 const value_type &operator()(const std::pair<Key, T> &key_value) const
106 {
107 return key_value.second;
108 }
109
110 value_type &operator()(std::pair<Key, T> &key_value) { return key_value.second; }
111 };
112
113 using overflow_container_type = std::list<std::pair<Key, T>, Allocator>;
114 using ht =
116 KeyEqual, Allocator, NeighborhoodSize, StoreHash,
117 GrowthPolicy, overflow_container_type>;
118
119 public:
120 using key_type = typename ht::key_type;
121 using mapped_type = T;
122 using value_type = typename ht::value_type;
123 using size_type = typename ht::size_type;
125 using hasher = typename ht::hasher;
126 using key_equal = typename ht::key_equal;
128 using reference = typename ht::reference;
130 using pointer = typename ht::pointer;
132 using iterator = typename ht::iterator;
134
135 /*
136 * Constructors
137 */
138 hopscotch_map() : hopscotch_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {}
139
140 explicit hopscotch_map(size_type bucket_count, const Hash &hash = Hash(),
141 const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator())
142 : m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
143 {
144 }
145
146 hopscotch_map(size_type bucket_count, const Allocator &alloc)
147 : hopscotch_map(bucket_count, Hash(), KeyEqual(), alloc)
148 {
149 }
150
151 hopscotch_map(size_type bucket_count, const Hash &hash, const Allocator &alloc)
152 : hopscotch_map(bucket_count, hash, KeyEqual(), alloc)
153 {
154 }
155
156 explicit hopscotch_map(const Allocator &alloc)
157 : hopscotch_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc)
158 {
159 }
160
161 template <class InputIt>
162 hopscotch_map(InputIt first, InputIt last,
163 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash = Hash(),
164 const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator())
165 : hopscotch_map(bucket_count, hash, equal, alloc)
166 {
167 insert(first, last);
168 }
169
170 template <class InputIt>
171 hopscotch_map(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc)
172 : hopscotch_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
173 {
174 }
175
176 template <class InputIt>
177 hopscotch_map(InputIt first, InputIt last, size_type bucket_count, const Hash &hash,
178 const Allocator &alloc)
179 : hopscotch_map(first, last, bucket_count, hash, KeyEqual(), alloc)
180 {
181 }
182
183 hopscotch_map(std::initializer_list<value_type> init,
184 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash = Hash(),
185 const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator())
186 : hopscotch_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
187 {
188 }
189
190 hopscotch_map(std::initializer_list<value_type> init, size_type bucket_count,
191 const Allocator &alloc)
192 : hopscotch_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
193 {
194 }
195
196 hopscotch_map(std::initializer_list<value_type> init, size_type bucket_count, const Hash &hash,
197 const Allocator &alloc)
198 : hopscotch_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
199 {
200 }
201
202 hopscotch_map &operator=(std::initializer_list<value_type> ilist)
203 {
204 m_ht.clear();
205
206 m_ht.reserve(ilist.size());
207 m_ht.insert(ilist.begin(), ilist.end());
208
209 return *this;
210 }
211
213
214 /*
215 * Iterators
216 */
217 iterator begin() noexcept { return m_ht.begin(); }
218 const_iterator begin() const noexcept { return m_ht.begin(); }
219 const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
220
221 iterator end() noexcept { return m_ht.end(); }
222 const_iterator end() const noexcept { return m_ht.end(); }
223 const_iterator cend() const noexcept { return m_ht.cend(); }
224
225 /*
226 * Capacity
227 */
228 bool empty() const noexcept { return m_ht.empty(); }
229 size_type size() const noexcept { return m_ht.size(); }
230 size_type max_size() const noexcept { return m_ht.max_size(); }
231
232 /*
233 * Modifiers
234 */
235 void clear() noexcept { m_ht.clear(); }
236
237 std::pair<iterator, bool> insert(const value_type &value) { return m_ht.insert(value); }
238
239 template <class P, typename std::enable_if<std::is_constructible<value_type, P &&>::value>::type
240 * = nullptr>
241 std::pair<iterator, bool> insert(P &&value)
242 {
243 return m_ht.insert(std::forward<P>(value));
244 }
245
246 std::pair<iterator, bool> insert(value_type &&value) { return m_ht.insert(std::move(value)); }
247
249 {
250 return m_ht.insert(hint, value);
251 }
252
253 template <class P, typename std::enable_if<std::is_constructible<value_type, P &&>::value>::type
254 * = nullptr>
256 {
257 return m_ht.insert(hint, std::forward<P>(value));
258 }
259
261 {
262 return m_ht.insert(hint, std::move(value));
263 }
264
265 template <class InputIt> void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }
266
267 void insert(std::initializer_list<value_type> ilist)
268 {
269 m_ht.insert(ilist.begin(), ilist.end());
270 }
271
272 template <class M> std::pair<iterator, bool> insert_or_assign(const key_type &k, M &&obj)
273 {
274 return m_ht.insert_or_assign(k, std::forward<M>(obj));
275 }
276
277 template <class M> std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj)
278 {
279 return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
280 }
281
282 template <class M> iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj)
283 {
284 return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
285 }
286
287 template <class M> iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj)
288 {
289 return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
290 }
291
292 /**
293 * Due to the way elements are stored, emplace will need to move or copy the
294 * key-value once. The method is equivalent to
295 * insert(value_type(std::forward<Args>(args)...));
296 *
297 * Mainly here for compatibility with the std::unordered_map interface.
298 */
299 template <class... Args> std::pair<iterator, bool> emplace(Args &&...args)
300 {
301 return m_ht.emplace(std::forward<Args>(args)...);
302 }
303
304 /**
305 * Due to the way elements are stored, emplace_hint will need to move or copy
306 * the key-value once. The method is equivalent to insert(hint,
307 * value_type(std::forward<Args>(args)...));
308 *
309 * Mainly here for compatibility with the std::unordered_map interface.
310 */
311 template <class... Args> iterator emplace_hint(const_iterator hint, Args &&...args)
312 {
313 return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
314 }
315
316 template <class... Args>
317 std::pair<iterator, bool> try_emplace(const key_type &k, Args &&...args)
318 {
319 return m_ht.try_emplace(k, std::forward<Args>(args)...);
320 }
321
322 template <class... Args> std::pair<iterator, bool> try_emplace(key_type &&k, Args &&...args)
323 {
324 return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
325 }
326
327 template <class... Args>
328 iterator try_emplace(const_iterator hint, const key_type &k, Args &&...args)
329 {
330 return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);
331 }
332
333 template <class... Args> iterator try_emplace(const_iterator hint, key_type &&k, Args &&...args)
334 {
335 return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);
336 }
337
338 iterator erase(iterator pos) { return m_ht.erase(pos); }
339 iterator erase(const_iterator pos) { return m_ht.erase(pos); }
340 iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
341 size_type erase(const key_type &key) { return m_ht.erase(key); }
342
343 /**
344 * Use the hash value 'precalculated_hash' instead of hashing the key. The
345 * hash value should be the same as hash_function()(key). Useful to speed-up
346 * the lookup to the value if you already have the hash.
347 */
348 size_type erase(const key_type &key, std::size_t precalculated_hash)
349 {
350 return m_ht.erase(key, precalculated_hash);
351 }
352
353 /**
354 * This overload only participates in the overload resolution if the typedef
355 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
356 * to Key.
357 */
358 template <class K, class KE = KeyEqual,
359 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
360 size_type erase(const K &key)
361 {
362 return m_ht.erase(key);
363 }
364
365 /**
366 * Use the hash value 'precalculated_hash' instead of hashing the key. The
367 * hash value should be the same as hash_function()(key). Useful to speed-up
368 * the lookup to the value if you already have the hash.
369 */
370 template <class K, class KE = KeyEqual,
371 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
372 size_type erase(const K &key, std::size_t precalculated_hash)
373 {
374 return m_ht.erase(key, precalculated_hash);
375 }
376
377 void swap(hopscotch_map &other) { other.m_ht.swap(m_ht); }
378
379 /*
380 * Lookup
381 */
382 T &at(const Key &key) { return m_ht.at(key); }
383
384 /**
385 * Use the hash value 'precalculated_hash' instead of hashing the key. The
386 * hash value should be the same as hash_function()(key). Useful to speed-up
387 * the lookup if you already have the hash.
388 */
389 T &at(const Key &key, std::size_t precalculated_hash)
390 {
391 return m_ht.at(key, precalculated_hash);
392 }
393
394 const T &at(const Key &key) const { return m_ht.at(key); }
395
396 /**
397 */
398 const T &at(const Key &key, std::size_t precalculated_hash) const
399 {
400 return m_ht.at(key, precalculated_hash);
401 }
402
403 /**
404 * This overload only participates in the overload resolution if the typedef
405 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
406 * to Key.
407 */
408 template <class K, class KE = KeyEqual,
409 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
410 T &at(const K &key)
411 {
412 return m_ht.at(key);
413 }
414
415 /**
416 * Use the hash value 'precalculated_hash' instead of hashing the key. The
417 * hash value should be the same as hash_function()(key). Useful to speed-up
418 * the lookup if you already have the hash.
419 */
420 template <class K, class KE = KeyEqual,
421 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
422 T &at(const K &key, std::size_t precalculated_hash)
423 {
424 return m_ht.at(key, precalculated_hash);
425 }
426
427 /**
428 */
429 template <class K, class KE = KeyEqual,
430 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
431 const T &at(const K &key) const
432 {
433 return m_ht.at(key);
434 }
435
436 /**
437 */
438 template <class K, class KE = KeyEqual,
439 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
440 const T &at(const K &key, std::size_t precalculated_hash) const
441 {
442 return m_ht.at(key, precalculated_hash);
443 }
444
445 T &operator[](const Key &key) { return m_ht[key]; }
446 T &operator[](Key &&key) { return m_ht[std::move(key)]; }
447
448 size_type count(const Key &key) const { return m_ht.count(key); }
449
450 /**
451 * Use the hash value 'precalculated_hash' instead of hashing the key. The
452 * hash value should be the same as hash_function()(key). Useful to speed-up
453 * the lookup if you already have the hash.
454 */
455 size_type count(const Key &key, std::size_t precalculated_hash) const
456 {
457 return m_ht.count(key, precalculated_hash);
458 }
459
460 /**
461 * This overload only participates in the overload resolution if the typedef
462 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
463 * to Key.
464 */
465 template <class K, class KE = KeyEqual,
466 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
467 size_type count(const K &key) const
468 {
469 return m_ht.count(key);
470 }
471
472 /**
473 * Use the hash value 'precalculated_hash' instead of hashing the key. The
474 * hash value should be the same as hash_function()(key). Useful to speed-up
475 * the lookup if you already have the hash.
476 */
477 template <class K, class KE = KeyEqual,
478 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
479 size_type count(const K &key, std::size_t precalculated_hash) const
480 {
481 return m_ht.count(key, precalculated_hash);
482 }
483
484 iterator find(const Key &key) { return m_ht.find(key); }
485
486 /**
487 * Use the hash value 'precalculated_hash' instead of hashing the key. The
488 * hash value should be the same as hash_function()(key). Useful to speed-up
489 * the lookup if you already have the hash.
490 */
491 iterator find(const Key &key, std::size_t precalculated_hash)
492 {
493 return m_ht.find(key, precalculated_hash);
494 }
495
496 const_iterator find(const Key &key) const { return m_ht.find(key); }
497
498 /**
499 */
500 const_iterator find(const Key &key, std::size_t precalculated_hash) const
501 {
502 return m_ht.find(key, precalculated_hash);
503 }
504
505 /**
506 * This overload only participates in the overload resolution if the typedef
507 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
508 * to Key.
509 */
510 template <class K, class KE = KeyEqual,
511 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
512 iterator find(const K &key)
513 {
514 return m_ht.find(key);
515 }
516
517 /**
518 * Use the hash value 'precalculated_hash' instead of hashing the key. The
519 * hash value should be the same as hash_function()(key). Useful to speed-up
520 * the lookup if you already have the hash.
521 */
522 template <class K, class KE = KeyEqual,
523 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
524 iterator find(const K &key, std::size_t precalculated_hash)
525 {
526 return m_ht.find(key, precalculated_hash);
527 }
528
529 /**
530 */
531 template <class K, class KE = KeyEqual,
532 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
533 const_iterator find(const K &key) const
534 {
535 return m_ht.find(key);
536 }
537
538 /**
539 * Use the hash value 'precalculated_hash' instead of hashing the key. The
540 * hash value should be the same as hash_function()(key). Useful to speed-up
541 * the lookup if you already have the hash.
542 */
543 template <class K, class KE = KeyEqual,
544 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
545 const_iterator find(const K &key, std::size_t precalculated_hash) const
546 {
547 return m_ht.find(key, precalculated_hash);
548 }
549
550 bool contains(const Key &key) const { return m_ht.contains(key); }
551
552 /**
553 * Use the hash value 'precalculated_hash' instead of hashing the key. The
554 * hash value should be the same as hash_function()(key). Useful to speed-up
555 * the lookup if you already have the hash.
556 */
557 bool contains(const Key &key, std::size_t precalculated_hash) const
558 {
559 return m_ht.contains(key, precalculated_hash);
560 }
561
562 /**
563 * This overload only participates in the overload resolution if the typedef
564 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
565 * to Key.
566 */
567 template <class K, class KE = KeyEqual,
568 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
569 bool contains(const K &key) const
570 {
571 return m_ht.contains(key);
572 }
573
574 /**
575 * Use the hash value 'precalculated_hash' instead of hashing the key. The
576 * hash value should be the same as hash_function()(key). Useful to speed-up
577 * the lookup if you already have the hash.
578 */
579 template <class K, class KE = KeyEqual,
580 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
581 bool contains(const K &key, std::size_t precalculated_hash) const
582 {
583 return m_ht.contains(key, precalculated_hash);
584 }
585
586 std::pair<iterator, iterator> equal_range(const Key &key) { return m_ht.equal_range(key); }
587
588 /**
589 * Use the hash value 'precalculated_hash' instead of hashing the key. The
590 * hash value should be the same as hash_function()(key). Useful to speed-up
591 * the lookup if you already have the hash.
592 */
593 std::pair<iterator, iterator> equal_range(const Key &key, std::size_t precalculated_hash)
594 {
595 return m_ht.equal_range(key, precalculated_hash);
596 }
597
598 std::pair<const_iterator, const_iterator> equal_range(const Key &key) const
599 {
600 return m_ht.equal_range(key);
601 }
602
603 /**
604 */
605 std::pair<const_iterator, const_iterator> equal_range(const Key &key,
606 std::size_t precalculated_hash) const
607 {
608 return m_ht.equal_range(key, precalculated_hash);
609 }
610
611 /**
612 * This overload only participates in the overload resolution if the typedef
613 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
614 * to Key.
615 */
616 template <class K, class KE = KeyEqual,
617 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
618 std::pair<iterator, iterator> equal_range(const K &key)
619 {
620 return m_ht.equal_range(key);
621 }
622
623 /**
624 * Use the hash value 'precalculated_hash' instead of hashing the key. The
625 * hash value should be the same as hash_function()(key). Useful to speed-up
626 * the lookup if you already have the hash.
627 */
628 template <class K, class KE = KeyEqual,
629 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
630 std::pair<iterator, iterator> equal_range(const K &key, std::size_t precalculated_hash)
631 {
632 return m_ht.equal_range(key, precalculated_hash);
633 }
634
635 /**
636 */
637 template <class K, class KE = KeyEqual,
638 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
639 std::pair<const_iterator, const_iterator> equal_range(const K &key) const
640 {
641 return m_ht.equal_range(key);
642 }
643
644 /**
645 */
646 template <class K, class KE = KeyEqual,
647 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
648 std::pair<const_iterator, const_iterator> equal_range(const K &key,
649 std::size_t precalculated_hash) const
650 {
651 return m_ht.equal_range(key, precalculated_hash);
652 }
653
654 /*
655 * Bucket interface
656 */
659
660 /*
661 * Hash policy
662 */
663 float load_factor() const { return m_ht.load_factor(); }
664 float max_load_factor() const { return m_ht.max_load_factor(); }
665 void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
666
667 void rehash(size_type count_) { m_ht.rehash(count_); }
668 void reserve(size_type count_) { m_ht.reserve(count_); }
669
670 /*
671 * Observers
672 */
674 key_equal key_eq() const { return m_ht.key_eq(); }
675
676 /*
677 * Other
678 */
679
680 /**
681 * Convert a const_iterator to an iterator.
682 */
684
685 size_type overflow_size() const noexcept { return m_ht.overflow_size(); }
686
687 friend bool operator==(const hopscotch_map &lhs, const hopscotch_map &rhs)
688 {
689 if (lhs.size() != rhs.size()) {
690 return false;
691 }
692
693 for (const auto &element_lhs : lhs) {
694 const auto it_element_rhs = rhs.find(element_lhs.first);
695 if (it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) {
696 return false;
697 }
698 }
699
700 return true;
701 }
702
703 friend bool operator!=(const hopscotch_map &lhs, const hopscotch_map &rhs)
704 {
705 return !operator==(lhs, rhs);
706 }
707
708 friend void swap(hopscotch_map &lhs, hopscotch_map &rhs) { lhs.swap(rhs); }
709
710 private:
712 };
713
714 /**
715 * Same as `tsl::hopscotch_map<Key, T, Hash, KeyEqual, Allocator,
716 * NeighborhoodSize, StoreHash, tsl::hh::prime_growth_policy>`.
717 */
718 template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
719 class Allocator = std::allocator<std::pair<Key, T>>, unsigned int NeighborhoodSize = 62,
720 bool StoreHash = false>
721 using hopscotch_pg_map = hopscotch_map<Key, T, Hash, KeyEqual, Allocator, NeighborhoodSize,
723
724} // end namespace tsl
725
726#endif
Definition hopscotch_hash.h:431
const_iterator cend() const noexcept
Definition hopscotch_hash.h:772
std::pair< iterator, bool > emplace(Args &&...args)
Definition hopscotch_hash.h:890
void swap(hopscotch_hash &other)
Definition hopscotch_hash.h:994
std::size_t size_type
Definition hopscotch_hash.h:446
Hash hasher
Definition hopscotch_hash.h:448
value_type & reference
Definition hopscotch_hash.h:451
bool contains(const K &key) const
Definition hopscotch_hash.h:1094
const_iterator cbegin() const noexcept
Definition hopscotch_hash.h:755
size_type max_size() const noexcept
Definition hopscotch_hash.h:785
hopscotch_iterator< true > const_iterator
Definition hopscotch_hash.h:456
float max_load_factor() const
Definition hopscotch_hash.h:1162
value_type * pointer
Definition hopscotch_hash.h:453
size_type count(const K &key) const
Definition hopscotch_hash.h:1070
std::pair< iterator, bool > insert(const value_type &value)
Definition hopscotch_hash.h:800
key_equal key_eq() const
Definition hopscotch_hash.h:1187
std::ptrdiff_t difference_type
Definition hopscotch_hash.h:447
static const size_type DEFAULT_INIT_BUCKETS_SIZE
Definition hopscotch_hash.h:1786
float load_factor() const
Definition hopscotch_hash.h:1153
allocator_type get_allocator() const
Definition hopscotch_hash.h:738
bool empty() const noexcept
Definition hopscotch_hash.h:781
KeyEqual key_equal
Definition hopscotch_hash.h:449
iterator erase(iterator pos)
Definition hopscotch_hash.h:935
U::value_type & at(const K &key)
Definition hopscotch_hash.h:1015
iterator begin() noexcept
Definition hopscotch_hash.h:743
const value_type * const_pointer
Definition hopscotch_hash.h:454
std::pair< iterator, iterator > equal_range(const K &key)
Definition hopscotch_hash.h:1101
Allocator allocator_type
Definition hopscotch_hash.h:450
size_type bucket_count() const
Definition hopscotch_hash.h:1128
std::pair< iterator, bool > insert_or_assign(const key_type &k, M &&obj)
Definition hopscotch_hash.h:856
size_type max_bucket_count() const
Definition hopscotch_hash.h:1143
void clear() noexcept
Definition hopscotch_hash.h:790
std::pair< iterator, bool > try_emplace(const key_type &k, Args &&...args)
Definition hopscotch_hash.h:901
hasher hash_function() const
Definition hopscotch_hash.h:1185
size_type size() const noexcept
Definition hopscotch_hash.h:783
hopscotch_iterator< false > iterator
Definition hopscotch_hash.h:455
iterator emplace_hint(const_iterator hint, Args &&...args)
Definition hopscotch_hash.h:895
typename KeySelect::key_type key_type
Definition hopscotch_hash.h:444
void rehash(size_type count_)
Definition hopscotch_hash.h:1171
const value_type & const_reference
Definition hopscotch_hash.h:452
iterator end() noexcept
Definition hopscotch_hash.h:765
iterator mutable_iterator(const_iterator pos)
Definition hopscotch_hash.h:1192
void reserve(size_type count_)
Definition hopscotch_hash.h:1177
iterator find(const K &key)
Definition hopscotch_hash.h:1077
size_type overflow_size() const noexcept
Definition hopscotch_hash.h:1207
ValueType value_type
Definition hopscotch_hash.h:445
Definition hopscotch_growth_policy.h:350
Definition hopscotch_map.h:88
key_type & operator()(std::pair< Key, T > &key_value)
Definition hopscotch_map.h:97
const key_type & operator()(const std::pair< Key, T > &key_value) const
Definition hopscotch_map.h:92
Key key_type
Definition hopscotch_map.h:90
Definition hopscotch_map.h:101
T value_type
Definition hopscotch_map.h:103
value_type & operator()(std::pair< Key, T > &key_value)
Definition hopscotch_map.h:110
const value_type & operator()(const std::pair< Key, T > &key_value) const
Definition hopscotch_map.h:105
Definition hopscotch_map.h:82
hopscotch_map(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc)
Definition hopscotch_map.h:171
bool contains(const K &key) const
Definition hopscotch_map.h:569
std::pair< iterator, bool > try_emplace(const key_type &k, Args &&...args)
Definition hopscotch_map.h:317
size_type count(const Key &key) const
Definition hopscotch_map.h:448
T & operator[](Key &&key)
Definition hopscotch_map.h:446
size_type erase(const key_type &key)
Definition hopscotch_map.h:341
const_iterator cend() const noexcept
Definition hopscotch_map.h:223
typename ht::pointer pointer
Definition hopscotch_map.h:130
T mapped_type
Definition hopscotch_map.h:121
iterator insert(const_iterator hint, const value_type &value)
Definition hopscotch_map.h:248
void insert(std::initializer_list< value_type > ilist)
Definition hopscotch_map.h:267
typename ht::reference reference
Definition hopscotch_map.h:128
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:630
void clear() noexcept
Definition hopscotch_map.h:235
iterator find(const K &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:524
ht m_ht
Definition hopscotch_map.h:711
const T & at(const K &key) const
Definition hopscotch_map.h:431
hasher hash_function() const
Definition hopscotch_map.h:673
const T & at(const K &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:440
iterator erase(iterator pos)
Definition hopscotch_map.h:338
size_type erase(const key_type &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:348
typename ht::size_type size_type
Definition hopscotch_map.h:123
std::pair< iterator, bool > insert(const value_type &value)
Definition hopscotch_map.h:237
iterator end() noexcept
Definition hopscotch_map.h:221
iterator erase(const_iterator pos)
Definition hopscotch_map.h:339
typename ht::key_type key_type
Definition hopscotch_map.h:120
iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj)
Definition hopscotch_map.h:282
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:593
iterator erase(const_iterator first, const_iterator last)
Definition hopscotch_map.h:340
iterator begin() noexcept
Definition hopscotch_map.h:217
const_iterator end() const noexcept
Definition hopscotch_map.h:222
const_iterator cbegin() const noexcept
Definition hopscotch_map.h:219
const_iterator begin() const noexcept
Definition hopscotch_map.h:218
hopscotch_map()
Definition hopscotch_map.h:138
friend bool operator!=(const hopscotch_map &lhs, const hopscotch_map &rhs)
Definition hopscotch_map.h:703
typename ht::hasher hasher
Definition hopscotch_map.h:125
size_type size() const noexcept
Definition hopscotch_map.h:229
const T & at(const Key &key) const
Definition hopscotch_map.h:394
hopscotch_map(InputIt first, InputIt last, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition hopscotch_map.h:177
void insert(InputIt first, InputIt last)
Definition hopscotch_map.h:265
void swap(hopscotch_map &other)
Definition hopscotch_map.h:377
void reserve(size_type count_)
Definition hopscotch_map.h:668
const_iterator find(const K &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:545
T & at(const K &key)
Definition hopscotch_map.h:410
hopscotch_map(size_type bucket_count, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition hopscotch_map.h:140
iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj)
Definition hopscotch_map.h:287
bool contains(const K &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:581
typename ht::const_reference const_reference
Definition hopscotch_map.h:129
typename ht::iterator iterator
Definition hopscotch_map.h:132
iterator try_emplace(const_iterator hint, key_type &&k, Args &&...args)
Definition hopscotch_map.h:333
T & operator[](const Key &key)
Definition hopscotch_map.h:445
T & at(const K &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:422
bool contains(const Key &key) const
Definition hopscotch_map.h:550
std::pair< iterator, bool > insert(value_type &&value)
Definition hopscotch_map.h:246
key_equal key_eq() const
Definition hopscotch_map.h:674
typename ht::const_pointer const_pointer
Definition hopscotch_map.h:131
typename ht::key_equal key_equal
Definition hopscotch_map.h:126
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition hopscotch_map.h:639
size_type erase(const K &key)
Definition hopscotch_map.h:360
typename ht::difference_type difference_type
Definition hopscotch_map.h:124
iterator find(const Key &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:491
hopscotch_map(size_type bucket_count, const Allocator &alloc)
Definition hopscotch_map.h:146
hopscotch_map(InputIt first, InputIt last, size_type bucket_count=ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition hopscotch_map.h:162
std::pair< iterator, iterator > equal_range(const Key &key)
Definition hopscotch_map.h:586
hopscotch_map(std::initializer_list< value_type > init, size_type bucket_count=ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition hopscotch_map.h:183
std::pair< iterator, bool > insert_or_assign(key_type &&k, M &&obj)
Definition hopscotch_map.h:277
iterator emplace_hint(const_iterator hint, Args &&...args)
Definition hopscotch_map.h:311
size_type erase(const K &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:372
const T & at(const Key &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:398
std::pair< iterator, bool > insert_or_assign(const key_type &k, M &&obj)
Definition hopscotch_map.h:272
friend bool operator==(const hopscotch_map &lhs, const hopscotch_map &rhs)
Definition hopscotch_map.h:687
size_type count(const K &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:479
void rehash(size_type count_)
Definition hopscotch_map.h:667
hopscotch_map(std::initializer_list< value_type > init, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition hopscotch_map.h:196
const_iterator find(const Key &key) const
Definition hopscotch_map.h:496
typename ht::allocator_type allocator_type
Definition hopscotch_map.h:127
float max_load_factor() const
Definition hopscotch_map.h:664
T & at(const Key &key, std::size_t precalculated_hash)
Definition hopscotch_map.h:389
typename ht::value_type value_type
Definition hopscotch_map.h:122
hopscotch_map & operator=(std::initializer_list< value_type > ilist)
Definition hopscotch_map.h:202
typename ht::const_iterator const_iterator
Definition hopscotch_map.h:133
iterator insert(const_iterator hint, P &&value)
Definition hopscotch_map.h:255
void max_load_factor(float ml)
Definition hopscotch_map.h:665
std::pair< iterator, bool > try_emplace(key_type &&k, Args &&...args)
Definition hopscotch_map.h:322
bool contains(const Key &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:557
std::pair< iterator, iterator > equal_range(const K &key)
Definition hopscotch_map.h:618
iterator try_emplace(const_iterator hint, const key_type &k, Args &&...args)
Definition hopscotch_map.h:328
std::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition hopscotch_map.h:598
hopscotch_map(std::initializer_list< value_type > init, size_type bucket_count, const Allocator &alloc)
Definition hopscotch_map.h:190
iterator insert(const_iterator hint, value_type &&value)
Definition hopscotch_map.h:260
float load_factor() const
Definition hopscotch_map.h:663
std::pair< iterator, bool > emplace(Args &&...args)
Definition hopscotch_map.h:299
hopscotch_map(size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition hopscotch_map.h:151
T & at(const Key &key)
Definition hopscotch_map.h:382
size_type count(const Key &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:455
allocator_type get_allocator() const
Definition hopscotch_map.h:212
size_type max_size() const noexcept
Definition hopscotch_map.h:230
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:648
size_type max_bucket_count() const
Definition hopscotch_map.h:658
bool empty() const noexcept
Definition hopscotch_map.h:228
std::pair< iterator, bool > insert(P &&value)
Definition hopscotch_map.h:241
hopscotch_map(const Allocator &alloc)
Definition hopscotch_map.h:156
const_iterator find(const Key &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:500
friend void swap(hopscotch_map &lhs, hopscotch_map &rhs)
Definition hopscotch_map.h:708
size_type count(const K &key) const
Definition hopscotch_map.h:467
size_type bucket_count() const
Definition hopscotch_map.h:657
const_iterator find(const K &key) const
Definition hopscotch_map.h:533
iterator find(const K &key)
Definition hopscotch_map.h:512
size_type overflow_size() const noexcept
Definition hopscotch_map.h:685
iterator mutable_iterator(const_iterator pos)
Definition hopscotch_map.h:683
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
Definition hopscotch_map.h:605
iterator find(const Key &key)
Definition hopscotch_map.h:484
std::list< std::pair< Key, T >, Allocator > overflow_container_type
Definition hopscotch_map.h:113
Definition bhopscotch_map.h:38