IOSS 2.0
Loading...
Searching...
No Matches
robin_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_ROBIN_MAP_H
25#define TSL_ROBIN_MAP_H
26
27#include <cstddef>
28#include <functional>
29#include <initializer_list>
30#include <memory>
31#include <type_traits>
32#include <utility>
33
34#include "robin_hash.h"
35
36namespace tsl {
37
38 /**
39 * Implementation of a hash map using open-addressing and the robin hood hashing
40 * algorithm with backward shift deletion.
41 *
42 * For operations modifying the hash map (insert, erase, rehash, ...), the
43 * strong exception guarantee is only guaranteed when the expression
44 * `std::is_nothrow_swappable<std::pair<Key, T>>\:\:value &&
45 * std::is_nothrow_move_constructible<std::pair<Key, T>>\:\:value` is true,
46 * otherwise if an exception is thrown during the swap or the move, the hash map
47 * may end up in a undefined state. Per the standard a `Key` or `T` with a
48 * noexcept copy constructor and no move constructor also satisfies the
49 * `std::is_nothrow_move_constructible<std::pair<Key, T>>\:\:value` criterion (and
50 * will thus guarantee the strong exception for the map).
51 *
52 * When `StoreHash` is true, 32 bits of the hash are stored alongside the
53 * values. It can improve the performance during lookups if the `KeyEqual`
54 * function takes time (if it engenders a cache-miss for example) as we then
55 * compare the stored hashes before comparing the keys. When
56 * `tsl::rh::power_of_two_growth_policy` is used as `GrowthPolicy`, it may also
57 * speed-up the rehash process as we can avoid to recalculate the hash. When it
58 * is detected that storing the hash will not incur any memory penalty due to
59 * alignment (i.e. `sizeof(tsl::detail_robin_hash::bucket_entry<ValueType,
60 * true>) == sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, false>)`)
61 * and `tsl::rh::power_of_two_growth_policy` is used, the hash will be stored
62 * even if `StoreHash` is false so that we can speed-up the rehash (but it will
63 * not be used on lookups unless `StoreHash` is true).
64 *
65 * `GrowthPolicy` defines how the map grows and consequently how a hash value is
66 * mapped to a bucket. By default the map uses
67 * `tsl::rh::power_of_two_growth_policy`. This policy keeps the number of
68 * buckets to a power of two and uses a mask to map the hash to a bucket instead
69 * of the slow modulo. Other growth policies are available and you may define
70 * your own growth policy, check `tsl::rh::power_of_two_growth_policy` for the
71 * interface.
72 *
73 * `std::pair<Key, T>` must be swappable.
74 *
75 * `Key` and `T` must be copy and/or move constructible.
76 *
77 * If the destructor of `Key` or `T` throws an exception, the behaviour of the
78 * class is undefined.
79 *
80 * Iterators invalidation:
81 * - clear, operator=, reserve, rehash: always invalidate the iterators.
82 * - insert, emplace, emplace_hint, operator[]: if there is an effective
83 * insert, invalidate the iterators.
84 * - erase: always invalidate the iterators.
85 */
86 template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
87 class Allocator = std::allocator<std::pair<Key, T>>, bool StoreHash = false,
88 class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>>
90 {
91 private:
93
95 {
96 public:
97 using key_type = Key;
98
99 const key_type &operator()(const std::pair<Key, T> &key_value) const noexcept
100 {
101 return key_value.first;
102 }
103
104 key_type &operator()(std::pair<Key, T> &key_value) noexcept { return key_value.first; }
105 };
106
108 {
109 public:
110 using value_type = T;
111
112 const value_type &operator()(const std::pair<Key, T> &key_value) const noexcept
113 {
114 return key_value.second;
115 }
116
117 value_type &operator()(std::pair<Key, T> &key_value) noexcept { return key_value.second; }
118 };
119
121 KeyEqual, Allocator, StoreHash, GrowthPolicy>;
122
123 public:
124 using key_type = typename ht::key_type;
125 using mapped_type = T;
126 using value_type = typename ht::value_type;
127 using size_type = typename ht::size_type;
129 using hasher = typename ht::hasher;
130 using key_equal = typename ht::key_equal;
132 using reference = typename ht::reference;
134 using pointer = typename ht::pointer;
136 using iterator = typename ht::iterator;
138
139 public:
140 /*
141 * Constructors
142 */
143 robin_map() : robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {}
144
145 explicit robin_map(size_type bucket_count, const Hash &hash = Hash(),
146 const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator())
147 : m_ht(bucket_count, hash, equal, alloc)
148 {
149 }
150
151 robin_map(size_type bucket_count, const Allocator &alloc)
152 : robin_map(bucket_count, Hash(), KeyEqual(), alloc)
153 {
154 }
155
156 robin_map(size_type bucket_count, const Hash &hash, const Allocator &alloc)
157 : robin_map(bucket_count, hash, KeyEqual(), alloc)
158 {
159 }
160
161 explicit robin_map(const Allocator &alloc) : robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {}
162
163 template <class InputIt>
165 const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(),
166 const Allocator &alloc = Allocator())
167 : robin_map(bucket_count, hash, equal, alloc)
168 {
169 insert(first, last);
170 }
171
172 template <class InputIt>
173 robin_map(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc)
174 : robin_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
175 {
176 }
177
178 template <class InputIt>
179 robin_map(InputIt first, InputIt last, size_type bucket_count, const Hash &hash,
180 const Allocator &alloc)
181 : robin_map(first, last, bucket_count, hash, KeyEqual(), alloc)
182 {
183 }
184
185 robin_map(std::initializer_list<value_type> init,
186 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash = Hash(),
187 const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator())
188 : robin_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
189 {
190 }
191
192 robin_map(std::initializer_list<value_type> init, size_type bucket_count,
193 const Allocator &alloc)
194 : robin_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
195 {
196 }
197
198 robin_map(std::initializer_list<value_type> init, size_type bucket_count, const Hash &hash,
199 const Allocator &alloc)
200 : robin_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
201 {
202 }
203
204 robin_map &operator=(std::initializer_list<value_type> ilist)
205 {
206 m_ht.clear();
207
208 m_ht.reserve(ilist.size());
209 m_ht.insert(ilist.begin(), ilist.end());
210
211 return *this;
212 }
213
215
216 /*
217 * Iterators
218 */
219 iterator begin() noexcept { return m_ht.begin(); }
220 const_iterator begin() const noexcept { return m_ht.begin(); }
221 const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
222
223 iterator end() noexcept { return m_ht.end(); }
224 const_iterator end() const noexcept { return m_ht.end(); }
225 const_iterator cend() const noexcept { return m_ht.cend(); }
226
227 /*
228 * Capacity
229 */
230 bool empty() const noexcept { return m_ht.empty(); }
231 size_type size() const noexcept { return m_ht.size(); }
232 size_type max_size() const noexcept { return m_ht.max_size(); }
233
234 /*
235 * Modifiers
236 */
237 void clear() noexcept { m_ht.clear(); }
238
239 std::pair<iterator, bool> insert(const value_type &value) { return m_ht.insert(value); }
240
241 template <class P, typename std::enable_if<std::is_constructible<value_type, P &&>::value>::type
242 * = nullptr>
243 std::pair<iterator, bool> insert(P &&value)
244 {
245 return m_ht.emplace(std::forward<P>(value));
246 }
247
248 std::pair<iterator, bool> insert(value_type &&value) { return m_ht.insert(std::move(value)); }
249
251 {
252 return m_ht.insert_hint(hint, value);
253 }
254
255 template <class P, typename std::enable_if<std::is_constructible<value_type, P &&>::value>::type
256 * = nullptr>
258 {
259 return m_ht.emplace_hint(hint, std::forward<P>(value));
260 }
261
263 {
264 return m_ht.insert_hint(hint, std::move(value));
265 }
266
267 template <class InputIt> void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }
268
269 void insert(std::initializer_list<value_type> ilist)
270 {
271 m_ht.insert(ilist.begin(), ilist.end());
272 }
273
274 template <class M> std::pair<iterator, bool> insert_or_assign(const key_type &k, M &&obj)
275 {
276 return m_ht.insert_or_assign(k, std::forward<M>(obj));
277 }
278
279 template <class M> std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj)
280 {
281 return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
282 }
283
284 template <class M> iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj)
285 {
286 return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
287 }
288
289 template <class M> iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj)
290 {
291 return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
292 }
293
294 /**
295 * Due to the way elements are stored, emplace will need to move or copy the
296 * key-value once. The method is equivalent to
297 * insert(value_type(std::forward<Args>(args)...));
298 *
299 * Mainly here for compatibility with the std::unordered_map interface.
300 */
301 template <class... Args> std::pair<iterator, bool> emplace(Args &&...args)
302 {
303 return m_ht.emplace(std::forward<Args>(args)...);
304 }
305
306 /**
307 * Due to the way elements are stored, emplace_hint will need to move or copy
308 * the key-value once. The method is equivalent to insert(hint,
309 * value_type(std::forward<Args>(args)...));
310 *
311 * Mainly here for compatibility with the std::unordered_map interface.
312 */
313 template <class... Args> iterator emplace_hint(const_iterator hint, Args &&...args)
314 {
315 return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
316 }
317
318 template <class... Args>
319 std::pair<iterator, bool> try_emplace(const key_type &k, Args &&...args)
320 {
321 return m_ht.try_emplace(k, std::forward<Args>(args)...);
322 }
323
324 template <class... Args> std::pair<iterator, bool> try_emplace(key_type &&k, Args &&...args)
325 {
326 return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
327 }
328
329 template <class... Args>
330 iterator try_emplace(const_iterator hint, const key_type &k, Args &&...args)
331 {
332 return m_ht.try_emplace_hint(hint, k, std::forward<Args>(args)...);
333 }
334
335 template <class... Args> iterator try_emplace(const_iterator hint, key_type &&k, Args &&...args)
336 {
337 return m_ht.try_emplace_hint(hint, std::move(k), std::forward<Args>(args)...);
338 }
339
340 iterator erase(iterator pos) { return m_ht.erase(pos); }
341 iterator erase(const_iterator pos) { return m_ht.erase(pos); }
342 iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
343 size_type erase(const key_type &key) { return m_ht.erase(key); }
344
345 /**
346 * Use the hash value 'precalculated_hash' instead of hashing the key. The
347 * hash value should be the same as hash_function()(key). Useful to speed-up
348 * the lookup to the value if you already have the hash.
349 */
350 size_type erase(const key_type &key, std::size_t precalculated_hash)
351 {
352 return m_ht.erase(key, precalculated_hash);
353 }
354
355 /**
356 * This overload only participates in the overload resolution if the typedef
357 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
358 * to Key.
359 */
360 template <class K, class KE = KeyEqual,
361 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
362 size_type erase(const K &key)
363 {
364 return m_ht.erase(key);
365 }
366
367 /**
368 * Use the hash value 'precalculated_hash' instead of hashing the key. The
369 * hash value should be the same as hash_function()(key). Useful to speed-up
370 * the lookup to the value if you already have the hash.
371 */
372 template <class K, class KE = KeyEqual,
373 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
374 size_type erase(const K &key, std::size_t precalculated_hash)
375 {
376 return m_ht.erase(key, precalculated_hash);
377 }
378
379 void swap(robin_map &other) { other.m_ht.swap(m_ht); }
380
381 /*
382 * Lookup
383 */
384 T &at(const Key &key) { return m_ht.at(key); }
385
386 /**
387 * Use the hash value 'precalculated_hash' instead of hashing the key. The
388 * hash value should be the same as hash_function()(key). Useful to speed-up
389 * the lookup if you already have the hash.
390 */
391 T &at(const Key &key, std::size_t precalculated_hash)
392 {
393 return m_ht.at(key, precalculated_hash);
394 }
395
396 const T &at(const Key &key) const { return m_ht.at(key); }
397
398 /**
399 */
400 const T &at(const Key &key, std::size_t precalculated_hash) const
401 {
402 return m_ht.at(key, precalculated_hash);
403 }
404
405 /**
406 * This overload only participates in the overload resolution if the typedef
407 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
408 * to Key.
409 */
410 template <class K, class KE = KeyEqual,
411 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
412 T &at(const K &key)
413 {
414 return m_ht.at(key);
415 }
416
417 /**
418 * Use the hash value 'precalculated_hash' instead of hashing the key. The
419 * hash value should be the same as hash_function()(key). Useful to speed-up
420 * the lookup if you already have the hash.
421 */
422 template <class K, class KE = KeyEqual,
423 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
424 T &at(const K &key, std::size_t precalculated_hash)
425 {
426 return m_ht.at(key, precalculated_hash);
427 }
428
429 /**
430 */
431 template <class K, class KE = KeyEqual,
432 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
433 const T &at(const K &key) const
434 {
435 return m_ht.at(key);
436 }
437
438 /**
439 */
440 template <class K, class KE = KeyEqual,
441 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
442 const T &at(const K &key, std::size_t precalculated_hash) const
443 {
444 return m_ht.at(key, precalculated_hash);
445 }
446
447 T &operator[](const Key &key) { return m_ht[key]; }
448 T &operator[](Key &&key) { return m_ht[std::move(key)]; }
449
450 size_type count(const Key &key) const { return m_ht.count(key); }
451
452 /**
453 * Use the hash value 'precalculated_hash' instead of hashing the key. The
454 * hash value should be the same as hash_function()(key). Useful to speed-up
455 * the lookup if you already have the hash.
456 */
457 size_type count(const Key &key, std::size_t precalculated_hash) const
458 {
459 return m_ht.count(key, precalculated_hash);
460 }
461
462 /**
463 * This overload only participates in the overload resolution if the typedef
464 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
465 * to Key.
466 */
467 template <class K, class KE = KeyEqual,
468 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
469 size_type count(const K &key) const
470 {
471 return m_ht.count(key);
472 }
473
474 /**
475 * Use the hash value 'precalculated_hash' instead of hashing the key. The
476 * hash value should be the same as hash_function()(key). Useful to speed-up
477 * the lookup if you already have the hash.
478 */
479 template <class K, class KE = KeyEqual,
480 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
481 size_type count(const K &key, std::size_t precalculated_hash) const
482 {
483 return m_ht.count(key, precalculated_hash);
484 }
485
486 iterator find(const Key &key) { return m_ht.find(key); }
487
488 /**
489 * Use the hash value 'precalculated_hash' instead of hashing the key. The
490 * hash value should be the same as hash_function()(key). Useful to speed-up
491 * the lookup if you already have the hash.
492 */
493 iterator find(const Key &key, std::size_t precalculated_hash)
494 {
495 return m_ht.find(key, precalculated_hash);
496 }
497
498 const_iterator find(const Key &key) const { return m_ht.find(key); }
499
500 /**
501 */
502 const_iterator find(const Key &key, std::size_t precalculated_hash) const
503 {
504 return m_ht.find(key, precalculated_hash);
505 }
506
507 /**
508 * This overload only participates in the overload resolution if the typedef
509 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
510 * to Key.
511 */
512 template <class K, class KE = KeyEqual,
513 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
514 iterator find(const K &key)
515 {
516 return m_ht.find(key);
517 }
518
519 /**
520 * Use the hash value 'precalculated_hash' instead of hashing the key. The
521 * hash value should be the same as hash_function()(key). Useful to speed-up
522 * the lookup if you already have the hash.
523 */
524 template <class K, class KE = KeyEqual,
525 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
526 iterator find(const K &key, std::size_t precalculated_hash)
527 {
528 return m_ht.find(key, precalculated_hash);
529 }
530
531 /**
532 */
533 template <class K, class KE = KeyEqual,
534 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
535 const_iterator find(const K &key) const
536 {
537 return m_ht.find(key);
538 }
539
540 /**
541 * Use the hash value 'precalculated_hash' instead of hashing the key. The
542 * hash value should be the same as hash_function()(key). Useful to speed-up
543 * the lookup if you already have the hash.
544 */
545 template <class K, class KE = KeyEqual,
546 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
547 const_iterator find(const K &key, std::size_t precalculated_hash) const
548 {
549 return m_ht.find(key, precalculated_hash);
550 }
551
552 bool contains(const Key &key) const { return m_ht.contains(key); }
553
554 /**
555 * Use the hash value 'precalculated_hash' instead of hashing the key. The
556 * hash value should be the same as hash_function()(key). Useful to speed-up
557 * the lookup if you already have the hash.
558 */
559 bool contains(const Key &key, std::size_t precalculated_hash) const
560 {
561 return m_ht.contains(key, precalculated_hash);
562 }
563
564 /**
565 * This overload only participates in the overload resolution if the typedef
566 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
567 * to Key.
568 */
569 template <class K, class KE = KeyEqual,
570 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
571 bool contains(const K &key) const
572 {
573 return m_ht.contains(key);
574 }
575
576 /**
577 * Use the hash value 'precalculated_hash' instead of hashing the key. The
578 * hash value should be the same as hash_function()(key). Useful to speed-up
579 * the lookup if you already have the hash.
580 */
581 template <class K, class KE = KeyEqual,
582 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
583 bool contains(const K &key, std::size_t precalculated_hash) const
584 {
585 return m_ht.contains(key, precalculated_hash);
586 }
587
588 std::pair<iterator, iterator> equal_range(const Key &key) { return m_ht.equal_range(key); }
589
590 /**
591 * Use the hash value 'precalculated_hash' instead of hashing the key. The
592 * hash value should be the same as hash_function()(key). Useful to speed-up
593 * the lookup if you already have the hash.
594 */
595 std::pair<iterator, iterator> equal_range(const Key &key, std::size_t precalculated_hash)
596 {
597 return m_ht.equal_range(key, precalculated_hash);
598 }
599
600 std::pair<const_iterator, const_iterator> equal_range(const Key &key) const
601 {
602 return m_ht.equal_range(key);
603 }
604
605 /**
606 */
607 std::pair<const_iterator, const_iterator> equal_range(const Key &key,
608 std::size_t precalculated_hash) const
609 {
610 return m_ht.equal_range(key, precalculated_hash);
611 }
612
613 /**
614 * This overload only participates in the overload resolution if the typedef
615 * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
616 * to Key.
617 */
618 template <class K, class KE = KeyEqual,
619 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
620 std::pair<iterator, iterator> equal_range(const K &key)
621 {
622 return m_ht.equal_range(key);
623 }
624
625 /**
626 * Use the hash value 'precalculated_hash' instead of hashing the key. The
627 * hash value should be the same as hash_function()(key). Useful to speed-up
628 * the lookup if you already have the hash.
629 */
630 template <class K, class KE = KeyEqual,
631 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
632 std::pair<iterator, iterator> equal_range(const K &key, std::size_t precalculated_hash)
633 {
634 return m_ht.equal_range(key, precalculated_hash);
635 }
636
637 /**
638 */
639 template <class K, class KE = KeyEqual,
640 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
641 std::pair<const_iterator, const_iterator> equal_range(const K &key) const
642 {
643 return m_ht.equal_range(key);
644 }
645
646 /**
647 */
648 template <class K, class KE = KeyEqual,
649 typename std::enable_if<has_is_transparent<KE>::value>::type * = nullptr>
650 std::pair<const_iterator, const_iterator> equal_range(const K &key,
651 std::size_t precalculated_hash) const
652 {
653 return m_ht.equal_range(key, precalculated_hash);
654 }
655
656 /*
657 * Bucket interface
658 */
661
662 /*
663 * Hash policy
664 */
665 float load_factor() const { return m_ht.load_factor(); }
666
667 float min_load_factor() const { return m_ht.min_load_factor(); }
668 float max_load_factor() const { return m_ht.max_load_factor(); }
669
670 /**
671 * Set the `min_load_factor` to `ml`. When the `load_factor` of the map goes
672 * below `min_load_factor` after some erase operations, the map will be
673 * shrunk when an insertion occurs. The erase method itself never shrinks
674 * the map.
675 *
676 * The default value of `min_load_factor` is 0.0f, the map never shrinks by
677 * default.
678 */
679 void min_load_factor(float ml) { m_ht.min_load_factor(ml); }
680 void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
681
682 void rehash(size_type my_count) { m_ht.rehash(my_count); }
683 void reserve(size_type my_count) { m_ht.reserve(my_count); }
684
685 /*
686 * Observers
687 */
689 key_equal key_eq() const { return m_ht.key_eq(); }
690
691 /*
692 * Other
693 */
694
695 /**
696 * Convert a const_iterator to an iterator.
697 */
699
700 /**
701 * Serialize the map through the `serializer` parameter.
702 *
703 * The `serializer` parameter must be a function object that supports the
704 * following call:
705 * - `template<typename U> void operator()(const U& value);` where the types
706 * `std::int16_t`, `std::uint32_t`, `std::uint64_t`, `float` and
707 * `std::pair<Key, T>` must be supported for U.
708 *
709 * The implementation leaves binary compatibility (endianness, IEEE 754 for
710 * floats, ...) of the types it serializes in the hands of the `Serializer`
711 * function object if compatibility is required.
712 */
713 template <class Serializer> void serialize(Serializer &serializer) const
714 {
715 m_ht.serialize(serializer);
716 }
717
718 /**
719 * Deserialize a previously serialized map through the `deserializer`
720 * parameter.
721 *
722 * The `deserializer` parameter must be a function object that supports the
723 * following call:
724 * - `template<typename U> U operator()();` where the types `std::int16_t`,
725 * `std::uint32_t`, `std::uint64_t`, `float` and `std::pair<Key, T>` must be
726 * supported for U.
727 *
728 * If the deserialized hash map type is hash compatible with the serialized
729 * map, the deserialization process can be sped up by setting
730 * `hash_compatible` to true. To be hash compatible, the Hash, KeyEqual and
731 * GrowthPolicy must behave the same way than the ones used on the serialized
732 * map and the StoreHash must have the same value. The `std::size_t` must also
733 * be of the same size as the one on the platform used to serialize the map.
734 * If these criteria are not met, the behaviour is undefined with
735 * `hash_compatible` sets to true.
736 *
737 * The behaviour is undefined if the type `Key` and `T` of the `robin_map` are
738 * not the same as the types used during serialization.
739 *
740 * The implementation leaves binary compatibility (endianness, IEEE 754 for
741 * floats, size of int, ...) of the types it deserializes in the hands of the
742 * `Deserializer` function object if compatibility is required.
743 */
744 template <class Deserializer>
745 static robin_map deserialize(Deserializer &deserializer, bool hash_compatible = false)
746 {
747 robin_map map(0);
748 map.m_ht.deserialize(deserializer, hash_compatible);
749
750 return map;
751 }
752
753 friend bool operator==(const robin_map &lhs, const robin_map &rhs)
754 {
755 if (lhs.size() != rhs.size()) {
756 return false;
757 }
758
759 for (const auto &element_lhs : lhs) {
760 const auto it_element_rhs = rhs.find(element_lhs.first);
761 if (it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) {
762 return false;
763 }
764 }
765
766 return true;
767 }
768
769 friend bool operator!=(const robin_map &lhs, const robin_map &rhs)
770 {
771 return !operator==(lhs, rhs);
772 }
773
774 friend void swap(robin_map &lhs, robin_map &rhs) { lhs.swap(rhs); }
775
776 private:
778 };
779
780 /**
781 * Same as `tsl::robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash,
782 * tsl::rh::prime_growth_policy>`.
783 */
784 template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
785 class Allocator = std::allocator<std::pair<Key, T>>, bool StoreHash = false>
788
789} // end namespace tsl
790
791#endif
Definition robin_hash.h:365
key_equal key_eq() const
Definition robin_hash.h:1073
static const size_type DEFAULT_INIT_BUCKETS_SIZE
Definition robin_hash.h:1508
iterator find(const K &key)
Definition robin_hash.h:972
Hash hasher
Definition robin_hash.h:382
const value_type * const_pointer
Definition robin_hash.h:388
iterator begin() noexcept
Definition robin_hash.h:664
bool empty() const noexcept
Definition robin_hash.h:695
typename KeySelect::key_type key_type
Definition robin_hash.h:378
float min_load_factor() const
Definition robin_hash.h:1041
KeyEqual key_equal
Definition robin_hash.h:383
std::pair< iterator, bool > insert(P &&value)
Definition robin_hash.h:719
hasher hash_function() const
Definition robin_hash.h:1071
value_type * pointer
Definition robin_hash.h:387
value_type & reference
Definition robin_hash.h:385
void rehash(size_type my_count)
Definition robin_hash.h:1057
std::pair< iterator, bool > try_emplace(K &&key, Args &&...args)
Definition robin_hash.h:783
void serialize(Serializer &serializer) const
Definition robin_hash.h:1083
bool contains(const K &key) const
Definition robin_hash.h:989
std::ptrdiff_t difference_type
Definition robin_hash.h:381
std::pair< iterator, bool > insert_or_assign(K &&key, M &&obj)
Definition robin_hash.h:751
std::pair< iterator, bool > emplace(Args &&...args)
Definition robin_hash.h:773
iterator insert_hint(const_iterator hint, P &&value)
Definition robin_hash.h:724
iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args)
Definition robin_hash.h:790
U::value_type & at(const K &key)
Definition robin_hash.h:920
size_type max_size() const noexcept
Definition robin_hash.h:699
const_iterator cbegin() const noexcept
Definition robin_hash.h:676
allocator_type get_allocator() const
Definition robin_hash.h:659
ValueType value_type
Definition robin_hash.h:379
robin_iterator< false > iterator
Definition robin_hash.h:389
float load_factor() const
Definition robin_hash.h:1032
const value_type & const_reference
Definition robin_hash.h:386
iterator erase(iterator pos)
Definition robin_hash.h:803
size_type bucket_count() const
Definition robin_hash.h:1022
void deserialize(Deserializer &deserializer, bool hash_compatible)
Definition robin_hash.h:1088
void swap(robin_hash &other)
Definition robin_hash.h:897
size_type count(const K &key) const
Definition robin_hash.h:960
const_iterator cend() const noexcept
Definition robin_hash.h:690
iterator end() noexcept
Definition robin_hash.h:686
float max_load_factor() const
Definition robin_hash.h:1043
size_type size() const noexcept
Definition robin_hash.h:697
std::pair< iterator, iterator > equal_range(const K &key)
Definition robin_hash.h:996
robin_iterator< true > const_iterator
Definition robin_hash.h:390
std::size_t size_type
Definition robin_hash.h:380
void reserve(size_type my_count)
Definition robin_hash.h:1063
iterator mutable_iterator(const_iterator pos)
Definition robin_hash.h:1078
Allocator allocator_type
Definition robin_hash.h:384
size_type max_bucket_count() const
Definition robin_hash.h:1024
iterator emplace_hint(const_iterator hint, Args &&...args)
Definition robin_hash.h:778
void clear() noexcept
Definition robin_hash.h:704
Definition robin_map.h:95
Key key_type
Definition robin_map.h:97
key_type & operator()(std::pair< Key, T > &key_value) noexcept
Definition robin_map.h:104
const key_type & operator()(const std::pair< Key, T > &key_value) const noexcept
Definition robin_map.h:99
Definition robin_map.h:108
T value_type
Definition robin_map.h:110
const value_type & operator()(const std::pair< Key, T > &key_value) const noexcept
Definition robin_map.h:112
value_type & operator()(std::pair< Key, T > &key_value) noexcept
Definition robin_map.h:117
Definition robin_map.h:90
robin_map(InputIt first, InputIt last, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition robin_map.h:179
float load_factor() const
Definition robin_map.h:665
typename ht::value_type value_type
Definition robin_map.h:126
float min_load_factor() const
Definition robin_map.h:667
typename ht::reference reference
Definition robin_map.h:132
std::pair< iterator, bool > try_emplace(key_type &&k, Args &&...args)
Definition robin_map.h:324
T & at(const Key &key)
Definition robin_map.h:384
friend bool operator!=(const robin_map &lhs, const robin_map &rhs)
Definition robin_map.h:769
typename ht::const_pointer const_pointer
Definition robin_map.h:135
std::pair< iterator, bool > insert(P &&value)
Definition robin_map.h:243
iterator insert(const_iterator hint, const value_type &value)
Definition robin_map.h:250
std::pair< iterator, bool > insert(const value_type &value)
Definition robin_map.h:239
size_type count(const Key &key) const
Definition robin_map.h:450
void clear() noexcept
Definition robin_map.h:237
T mapped_type
Definition robin_map.h:125
robin_map(size_type bucket_count, const Allocator &alloc)
Definition robin_map.h:151
size_type count(const Key &key, std::size_t precalculated_hash) const
Definition robin_map.h:457
typename ht::hasher hasher
Definition robin_map.h:129
size_type max_size() const noexcept
Definition robin_map.h:232
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
Definition robin_map.h:632
size_type count(const K &key) const
Definition robin_map.h:469
const_iterator find(const Key &key, std::size_t precalculated_hash) const
Definition robin_map.h:502
iterator find(const Key &key, std::size_t precalculated_hash)
Definition robin_map.h:493
typename ht::allocator_type allocator_type
Definition robin_map.h:131
T & operator[](const Key &key)
Definition robin_map.h:447
iterator erase(const_iterator pos)
Definition robin_map.h:341
bool empty() const noexcept
Definition robin_map.h:230
typename ht::pointer pointer
Definition robin_map.h:134
const_iterator find(const K &key) const
Definition robin_map.h:535
key_equal key_eq() const
Definition robin_map.h:689
size_type erase(const key_type &key)
Definition robin_map.h:343
iterator mutable_iterator(const_iterator pos)
Definition robin_map.h:698
robin_map(std::initializer_list< value_type > init, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition robin_map.h:198
size_type bucket_count() const
Definition robin_map.h:659
std::pair< iterator, iterator > equal_range(const Key &key)
Definition robin_map.h:588
std::pair< iterator, bool > try_emplace(const key_type &k, Args &&...args)
Definition robin_map.h:319
T & at(const Key &key, std::size_t precalculated_hash)
Definition robin_map.h:391
bool contains(const K &key) const
Definition robin_map.h:571
bool contains(const Key &key) const
Definition robin_map.h:552
robin_map(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc)
Definition robin_map.h:173
typename ht::difference_type difference_type
Definition robin_map.h:128
size_type erase(const key_type &key, std::size_t precalculated_hash)
Definition robin_map.h:350
iterator begin() noexcept
Definition robin_map.h:219
friend void swap(robin_map &lhs, robin_map &rhs)
Definition robin_map.h:774
iterator erase(const_iterator first, const_iterator last)
Definition robin_map.h:342
void rehash(size_type my_count)
Definition robin_map.h:682
bool contains(const K &key, std::size_t precalculated_hash) const
Definition robin_map.h:583
size_type max_bucket_count() const
Definition robin_map.h:660
const T & at(const K &key) const
Definition robin_map.h:433
allocator_type get_allocator() const
Definition robin_map.h:214
std::pair< iterator, iterator > equal_range(const K &key)
Definition robin_map.h:620
friend bool operator==(const robin_map &lhs, const robin_map &rhs)
Definition robin_map.h:753
const T & at(const Key &key) const
Definition robin_map.h:396
void insert(std::initializer_list< value_type > ilist)
Definition robin_map.h:269
typename ht::key_type key_type
Definition robin_map.h:124
iterator find(const K &key)
Definition robin_map.h:514
void reserve(size_type my_count)
Definition robin_map.h:683
hasher hash_function() const
Definition robin_map.h:688
void insert(InputIt first, InputIt last)
Definition robin_map.h:267
iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj)
Definition robin_map.h:284
const_iterator find(const Key &key) const
Definition robin_map.h:498
iterator insert(const_iterator hint, P &&value)
Definition robin_map.h:257
const_iterator begin() const noexcept
Definition robin_map.h:220
size_type erase(const K &key, std::size_t precalculated_hash)
Definition robin_map.h:374
void min_load_factor(float ml)
Definition robin_map.h:679
typename ht::const_reference const_reference
Definition robin_map.h:133
float max_load_factor() const
Definition robin_map.h:668
bool contains(const Key &key, std::size_t precalculated_hash) const
Definition robin_map.h:559
robin_map()
Definition robin_map.h:143
iterator try_emplace(const_iterator hint, const key_type &k, Args &&...args)
Definition robin_map.h:330
const_iterator cend() const noexcept
Definition robin_map.h:225
static robin_map deserialize(Deserializer &deserializer, bool hash_compatible=false)
Definition robin_map.h:745
robin_map & operator=(std::initializer_list< value_type > ilist)
Definition robin_map.h:204
typename ht::key_equal key_equal
Definition robin_map.h:130
typename ht::const_iterator const_iterator
Definition robin_map.h:137
iterator find(const Key &key)
Definition robin_map.h:486
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
Definition robin_map.h:650
std::pair< iterator, bool > emplace(Args &&...args)
Definition robin_map.h:301
T & at(const K &key)
Definition robin_map.h:412
void swap(robin_map &other)
Definition robin_map.h:379
size_type size() const noexcept
Definition robin_map.h:231
iterator end() noexcept
Definition robin_map.h:223
std::pair< iterator, bool > insert(value_type &&value)
Definition robin_map.h:248
void max_load_factor(float ml)
Definition robin_map.h:680
const T & at(const Key &key, std::size_t precalculated_hash) const
Definition robin_map.h:400
robin_map(size_type bucket_count, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition robin_map.h:145
const T & at(const K &key, std::size_t precalculated_hash) const
Definition robin_map.h:442
const_iterator find(const K &key, std::size_t precalculated_hash) const
Definition robin_map.h:547
iterator emplace_hint(const_iterator hint, Args &&...args)
Definition robin_map.h:313
robin_map(std::initializer_list< value_type > init, size_type bucket_count, const Allocator &alloc)
Definition robin_map.h:192
size_type erase(const K &key)
Definition robin_map.h:362
iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj)
Definition robin_map.h:289
size_type count(const K &key, std::size_t precalculated_hash) const
Definition robin_map.h:481
std::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition robin_map.h:600
T & operator[](Key &&key)
Definition robin_map.h:448
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
Definition robin_map.h:607
robin_map(size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition robin_map.h:156
const_iterator cbegin() const noexcept
Definition robin_map.h:221
typename ht::size_type size_type
Definition robin_map.h:127
iterator try_emplace(const_iterator hint, key_type &&k, Args &&...args)
Definition robin_map.h:335
void serialize(Serializer &serializer) const
Definition robin_map.h:713
const_iterator end() const noexcept
Definition robin_map.h:224
std::pair< iterator, bool > insert_or_assign(const key_type &k, M &&obj)
Definition robin_map.h:274
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition robin_map.h:641
T & at(const K &key, std::size_t precalculated_hash)
Definition robin_map.h:424
iterator erase(iterator pos)
Definition robin_map.h:340
std::pair< iterator, bool > insert_or_assign(key_type &&k, M &&obj)
Definition robin_map.h:279
robin_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 robin_map.h:164
iterator insert(const_iterator hint, value_type &&value)
Definition robin_map.h:262
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
Definition robin_map.h:595
ht m_ht
Definition robin_map.h:777
robin_map(const Allocator &alloc)
Definition robin_map.h:161
robin_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 robin_map.h:185
typename ht::iterator iterator
Definition robin_map.h:136
iterator find(const K &key, std::size_t precalculated_hash)
Definition robin_map.h:526
Definition bhopscotch_map.h:38