Loading...
Searching...
No Matches
robin_map.h
1
24#ifndef PXR_TSL_ROBIN_MAP_H
25#define PXR_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
36// Pixar modification, modify namespace for isolation.
37#include "pxr/pxr.h"
38
39PXR_NAMESPACE_OPEN_SCOPE
40
41namespace pxr_tsl {
42
91template <class Key, class T, class Hash = std::hash<Key>,
92 class KeyEqual = std::equal_to<Key>,
93 class Allocator = std::allocator<std::pair<Key, T>>,
94 bool StoreHash = false,
95 class GrowthPolicy = pxr_tsl::rh::power_of_two_growth_policy<2>>
96class robin_map {
97 private:
98 template <typename U>
99 using has_is_transparent = pxr_tsl::detail_robin_hash::has_is_transparent<U>;
100
101 class KeySelect {
102 public:
103 using key_type = Key;
104
105 const key_type& operator()(const std::pair<Key, T>& key_value) const
106 noexcept {
107 return key_value.first;
108 }
109
110 key_type& operator()(std::pair<Key, T>& key_value) noexcept {
111 return key_value.first;
112 }
113 };
114
115 class ValueSelect {
116 public:
117 using value_type = T;
118
119 const value_type& operator()(const std::pair<Key, T>& key_value) const
120 noexcept {
121 return key_value.second;
122 }
123
124 value_type& operator()(std::pair<Key, T>& key_value) noexcept {
125 return key_value.second;
126 }
127 };
128
130 ValueSelect, Hash, KeyEqual,
131 Allocator, StoreHash, GrowthPolicy>;
132
133 public:
134 using key_type = typename ht::key_type;
135 using mapped_type = T;
136 using value_type = typename ht::value_type;
137 using size_type = typename ht::size_type;
138 using difference_type = typename ht::difference_type;
139 using hasher = typename ht::hasher;
140 using key_equal = typename ht::key_equal;
141 using allocator_type = typename ht::allocator_type;
142 using reference = typename ht::reference;
143 using const_reference = typename ht::const_reference;
144 using pointer = typename ht::pointer;
145 using const_pointer = typename ht::const_pointer;
146 using iterator = typename ht::iterator;
147 using const_iterator = typename ht::const_iterator;
148
149 public:
150 /*
151 * Constructors
152 */
153 robin_map() : robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {}
154
155 explicit robin_map(size_type bucket_count, const Hash& hash = Hash(),
156 const KeyEqual& equal = KeyEqual(),
157 const Allocator& alloc = Allocator())
158 : m_ht(bucket_count, hash, equal, alloc) {}
159
160 robin_map(size_type bucket_count, const Allocator& alloc)
161 : robin_map(bucket_count, Hash(), KeyEqual(), alloc) {}
162
163 robin_map(size_type bucket_count, const Hash& hash, const Allocator& alloc)
164 : robin_map(bucket_count, hash, KeyEqual(), alloc) {}
165
166 explicit robin_map(const Allocator& alloc)
167 : robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {}
168
169 template <class InputIt>
170 robin_map(InputIt first, InputIt last,
171 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
172 const Hash& hash = Hash(), const KeyEqual& equal = KeyEqual(),
173 const Allocator& alloc = Allocator())
174 : robin_map(bucket_count, hash, equal, alloc) {
175 insert(first, last);
176 }
177
178 template <class InputIt>
179 robin_map(InputIt first, InputIt last, size_type bucket_count,
180 const Allocator& alloc)
181 : robin_map(first, last, bucket_count, Hash(), KeyEqual(), alloc) {}
182
183 template <class InputIt>
184 robin_map(InputIt first, InputIt last, size_type bucket_count,
185 const Hash& hash, const Allocator& alloc)
186 : robin_map(first, last, bucket_count, hash, KeyEqual(), alloc) {}
187
188 robin_map(std::initializer_list<value_type> init,
189 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
190 const Hash& hash = Hash(), const KeyEqual& equal = KeyEqual(),
191 const Allocator& alloc = Allocator())
192 : robin_map(init.begin(), init.end(), bucket_count, hash, equal, alloc) {}
193
194 robin_map(std::initializer_list<value_type> init, size_type bucket_count,
195 const Allocator& alloc)
196 : robin_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(),
197 alloc) {}
198
199 robin_map(std::initializer_list<value_type> init, size_type bucket_count,
200 const Hash& hash, const Allocator& alloc)
201 : robin_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(),
202 alloc) {}
203
204 robin_map& operator=(std::initializer_list<value_type> ilist) {
205 m_ht.clear();
206
207 m_ht.reserve(ilist.size());
208 m_ht.insert(ilist.begin(), ilist.end());
209
210 return *this;
211 }
212
213 allocator_type get_allocator() const { return m_ht.get_allocator(); }
214
215 /*
216 * Iterators
217 */
218 iterator begin() noexcept { return m_ht.begin(); }
219 const_iterator begin() const noexcept { return m_ht.begin(); }
220 const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
221
222 iterator end() noexcept { return m_ht.end(); }
223 const_iterator end() const noexcept { return m_ht.end(); }
224 const_iterator cend() const noexcept { return m_ht.cend(); }
225
226 /*
227 * Capacity
228 */
229 bool empty() const noexcept { return m_ht.empty(); }
230 size_type size() const noexcept { return m_ht.size(); }
231 size_type max_size() const noexcept { return m_ht.max_size(); }
232
233 /*
234 * Modifiers
235 */
236 void clear() noexcept { m_ht.clear(); }
237
238 std::pair<iterator, bool> insert(const value_type& value) {
239 return m_ht.insert(value);
240 }
241
242 template <class P, typename std::enable_if<std::is_constructible<
243 value_type, P&&>::value>::type* = nullptr>
244 std::pair<iterator, bool> insert(P&& value) {
245 return m_ht.emplace(std::forward<P>(value));
246 }
247
248 std::pair<iterator, bool> insert(value_type&& value) {
249 return m_ht.insert(std::move(value));
250 }
251
252 iterator insert(const_iterator hint, const value_type& value) {
253 return m_ht.insert_hint(hint, value);
254 }
255
256 template <class P, typename std::enable_if<std::is_constructible<
257 value_type, P&&>::value>::type* = nullptr>
258 iterator insert(const_iterator hint, P&& value) {
259 return m_ht.emplace_hint(hint, std::forward<P>(value));
260 }
261
262 iterator insert(const_iterator hint, value_type&& value) {
263 return m_ht.insert_hint(hint, std::move(value));
264 }
265
266 template <class InputIt>
267 void insert(InputIt first, InputIt last) {
268 m_ht.insert(first, last);
269 }
270
271 void insert(std::initializer_list<value_type> ilist) {
272 m_ht.insert(ilist.begin(), ilist.end());
273 }
274
275 template <class M>
276 std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) {
277 return m_ht.insert_or_assign(k, std::forward<M>(obj));
278 }
279
280 template <class M>
281 std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) {
282 return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
283 }
284
285 template <class M>
286 iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {
287 return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
288 }
289
290 template <class M>
291 iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {
292 return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
293 }
294
302 template <class... Args>
303 std::pair<iterator, bool> emplace(Args&&... args) {
304 return m_ht.emplace(std::forward<Args>(args)...);
305 }
306
314 template <class... Args>
315 iterator emplace_hint(const_iterator hint, Args&&... args) {
316 return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
317 }
318
319 template <class... Args>
320 std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) {
321 return m_ht.try_emplace(k, std::forward<Args>(args)...);
322 }
323
324 template <class... Args>
325 std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {
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 return m_ht.try_emplace_hint(hint, k, std::forward<Args>(args)...);
332 }
333
334 template <class... Args>
335 iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {
336 return m_ht.try_emplace_hint(hint, std::move(k),
337 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) {
343 return m_ht.erase(first, last);
344 }
345 size_type erase(const key_type& key) { return m_ht.erase(key); }
346
352 size_type erase(const key_type& key, std::size_t precalculated_hash) {
353 return m_ht.erase(key, precalculated_hash);
354 }
355
361 template <
362 class K, class KE = KeyEqual,
363 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
364 size_type erase(const K& key) {
365 return m_ht.erase(key);
366 }
367
375 template <
376 class K, class KE = KeyEqual,
377 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
378 size_type erase(const K& key, std::size_t precalculated_hash) {
379 return m_ht.erase(key, precalculated_hash);
380 }
381
382 void swap(robin_map& other) { other.m_ht.swap(m_ht); }
383
384 /*
385 * Lookup
386 */
387 T& at(const Key& key) { return m_ht.at(key); }
388
394 T& at(const Key& key, std::size_t precalculated_hash) {
395 return m_ht.at(key, precalculated_hash);
396 }
397
398 const T& at(const Key& key) const { return m_ht.at(key); }
399
403 const T& at(const Key& key, std::size_t precalculated_hash) const {
404 return m_ht.at(key, precalculated_hash);
405 }
406
412 template <
413 class K, class KE = KeyEqual,
414 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
415 T& at(const K& key) {
416 return m_ht.at(key);
417 }
418
426 template <
427 class K, class KE = KeyEqual,
428 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
429 T& at(const K& key, std::size_t precalculated_hash) {
430 return m_ht.at(key, precalculated_hash);
431 }
432
436 template <
437 class K, class KE = KeyEqual,
438 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
439 const T& at(const K& key) const {
440 return m_ht.at(key);
441 }
442
446 template <
447 class K, class KE = KeyEqual,
448 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
449 const T& at(const K& key, std::size_t precalculated_hash) const {
450 return m_ht.at(key, precalculated_hash);
451 }
452
453 T& operator[](const Key& key) { return m_ht[key]; }
454 T& operator[](Key&& key) { return m_ht[std::move(key)]; }
455
456 size_type count(const Key& key) const { return m_ht.count(key); }
457
463 size_type count(const Key& key, std::size_t precalculated_hash) const {
464 return m_ht.count(key, precalculated_hash);
465 }
466
472 template <
473 class K, class KE = KeyEqual,
474 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
475 size_type count(const K& key) const {
476 return m_ht.count(key);
477 }
478
486 template <
487 class K, class KE = KeyEqual,
488 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
489 size_type count(const K& key, std::size_t precalculated_hash) const {
490 return m_ht.count(key, precalculated_hash);
491 }
492
493 iterator find(const Key& key) { return m_ht.find(key); }
494
500 iterator find(const Key& key, std::size_t precalculated_hash) {
501 return m_ht.find(key, precalculated_hash);
502 }
503
504 const_iterator find(const Key& key) const { return m_ht.find(key); }
505
509 const_iterator find(const Key& key, std::size_t precalculated_hash) const {
510 return m_ht.find(key, precalculated_hash);
511 }
512
518 template <
519 class K, class KE = KeyEqual,
520 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
521 iterator find(const K& key) {
522 return m_ht.find(key);
523 }
524
532 template <
533 class K, class KE = KeyEqual,
534 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
535 iterator find(const K& key, std::size_t precalculated_hash) {
536 return m_ht.find(key, precalculated_hash);
537 }
538
542 template <
543 class K, class KE = KeyEqual,
544 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
545 const_iterator find(const K& key) const {
546 return m_ht.find(key);
547 }
548
556 template <
557 class K, class KE = KeyEqual,
558 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
559 const_iterator find(const K& key, std::size_t precalculated_hash) const {
560 return m_ht.find(key, precalculated_hash);
561 }
562
563 bool contains(const Key& key) const { return m_ht.contains(key); }
564
570 bool contains(const Key& key, std::size_t precalculated_hash) const {
571 return m_ht.contains(key, precalculated_hash);
572 }
573
579 template <
580 class K, class KE = KeyEqual,
581 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
582 bool contains(const K& key) const {
583 return m_ht.contains(key);
584 }
585
593 template <
594 class K, class KE = KeyEqual,
595 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
596 bool contains(const K& key, std::size_t precalculated_hash) const {
597 return m_ht.contains(key, precalculated_hash);
598 }
599
600 std::pair<iterator, iterator> equal_range(const Key& key) {
601 return m_ht.equal_range(key);
602 }
603
609 std::pair<iterator, iterator> equal_range(const Key& key,
610 std::size_t precalculated_hash) {
611 return m_ht.equal_range(key, precalculated_hash);
612 }
613
614 std::pair<const_iterator, const_iterator> equal_range(const Key& key) const {
615 return m_ht.equal_range(key);
616 }
617
621 std::pair<const_iterator, const_iterator> equal_range(
622 const Key& key, std::size_t precalculated_hash) const {
623 return m_ht.equal_range(key, precalculated_hash);
624 }
625
631 template <
632 class K, class KE = KeyEqual,
633 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
634 std::pair<iterator, iterator> equal_range(const K& key) {
635 return m_ht.equal_range(key);
636 }
637
645 template <
646 class K, class KE = KeyEqual,
647 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
648 std::pair<iterator, iterator> equal_range(const K& key,
649 std::size_t precalculated_hash) {
650 return m_ht.equal_range(key, precalculated_hash);
651 }
652
656 template <
657 class K, class KE = KeyEqual,
658 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
659 std::pair<const_iterator, const_iterator> equal_range(const K& key) const {
660 return m_ht.equal_range(key);
661 }
662
666 template <
667 class K, class KE = KeyEqual,
668 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
669 std::pair<const_iterator, const_iterator> equal_range(
670 const K& key, std::size_t precalculated_hash) const {
671 return m_ht.equal_range(key, precalculated_hash);
672 }
673
674 /*
675 * Bucket interface
676 */
677 size_type bucket_count() const { return m_ht.bucket_count(); }
678 size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
679
680 /*
681 * Hash policy
682 */
683 float load_factor() const { return m_ht.load_factor(); }
684
685 float min_load_factor() const { return m_ht.min_load_factor(); }
686 float max_load_factor() const { return m_ht.max_load_factor(); }
687
697 void min_load_factor(float ml) { m_ht.min_load_factor(ml); }
698 void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
699
700 void rehash(size_type count_) { m_ht.rehash(count_); }
701 void reserve(size_type count_) { m_ht.reserve(count_); }
702
703 /*
704 * Observers
705 */
706 hasher hash_function() const { return m_ht.hash_function(); }
707 key_equal key_eq() const { return m_ht.key_eq(); }
708
709 /*
710 * Other
711 */
712
716 iterator mutable_iterator(const_iterator pos) {
717 return m_ht.mutable_iterator(pos);
718 }
719
733 template <class Serializer>
734 void serialize(Serializer& serializer) const {
735 m_ht.serialize(serializer);
736 }
737
764 template <class Deserializer>
765 static robin_map deserialize(Deserializer& deserializer,
766 bool hash_compatible = false) {
767 robin_map map(0);
768 map.m_ht.deserialize(deserializer, hash_compatible);
769
770 return map;
771 }
772
773 friend bool operator==(const robin_map& lhs, const robin_map& rhs) {
774 if (lhs.size() != rhs.size()) {
775 return false;
776 }
777
778 for (const auto& element_lhs : lhs) {
779 const auto it_element_rhs = rhs.find(element_lhs.first);
780 if (it_element_rhs == rhs.cend() ||
781 element_lhs.second != it_element_rhs->second) {
782 return false;
783 }
784 }
785
786 return true;
787 }
788
789 friend bool operator!=(const robin_map& lhs, const robin_map& rhs) {
790 return !operator==(lhs, rhs);
791 }
792
793 friend void swap(robin_map& lhs, robin_map& rhs) { lhs.swap(rhs); }
794
795 private:
796 ht m_ht;
797};
798
803template <class Key, class T, class Hash = std::hash<Key>,
804 class KeyEqual = std::equal_to<Key>,
805 class Allocator = std::allocator<std::pair<Key, T>>,
806 bool StoreHash = false>
807using robin_pg_map = robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash,
809
810} // end namespace pxr_tsl
811
812PXR_NAMESPACE_CLOSE_SCOPE
813
814#endif
The 'operator*()' and 'operator->()' methods return a const reference and const pointer respectively ...
Definition: robin_hash.h:448
Internal common class used by robin_map and robin_set.
Definition: robin_hash.h:354
iterator erase(iterator pos)
Here to avoid template<class K> size_type erase(const K& key) being used when we use an iterator inst...
Definition: robin_hash.h:824
Grow the hash table by using prime numbers as bucket count.
Implementation of a hash map using open-addressing and the robin hood hashing algorithm with backward...
Definition: robin_map.h:96
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:609
bool contains(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:570
const_iterator find(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:559
const_iterator find(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:509
static robin_map deserialize(Deserializer &deserializer, bool hash_compatible=false)
Deserialize a previously serialized map through the deserializer parameter.
Definition: robin_map.h:765
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:659
const T & at(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:449
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:621
std::pair< iterator, iterator > equal_range(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:634
bool contains(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:596
void min_load_factor(float ml)
Set the min_load_factor to ml.
Definition: robin_map.h:697
size_type count(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:463
T & at(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:415
const_iterator find(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:545
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:669
size_type erase(const key_type &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:352
iterator find(const Key &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:500
T & at(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:429
iterator mutable_iterator(const_iterator pos)
Convert a const_iterator to an iterator.
Definition: robin_map.h:716
iterator emplace_hint(const_iterator hint, Args &&... args)
Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
Definition: robin_map.h:315
iterator find(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:535
bool contains(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:582
const T & at(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:439
size_type count(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:475
std::pair< iterator, bool > emplace(Args &&... args)
Due to the way elements are stored, emplace will need to move or copy the key-value once.
Definition: robin_map.h:303
size_type erase(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:364
const T & at(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:403
T & at(const Key &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:394
iterator find(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:521
size_type erase(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:378
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:648
size_type count(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:489
void serialize(Serializer &serializer) const
Serialize the map through the serializer parameter.
Definition: robin_map.h:734
MIT License.