HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 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 
40 
41 namespace pxr_tsl {
42 
43 /**
44  * Implementation of a hash map using open-addressing and the robin hood hashing
45  * algorithm with backward shift deletion.
46  *
47  * For operations modifying the hash map (insert, erase, rehash, ...), the
48  * strong exception guarantee is only guaranteed when the expression
49  * `std::is_nothrow_swappable<std::pair<Key, T>>::value &&
50  * std::is_nothrow_move_constructible<std::pair<Key, T>>::value` is true,
51  * otherwise if an exception is thrown during the swap or the move, the hash map
52  * may end up in a undefined state. Per the standard a `Key` or `T` with a
53  * noexcept copy constructor and no move constructor also satisfies the
54  * `std::is_nothrow_move_constructible<std::pair<Key, T>>::value` criterion (and
55  * will thus guarantee the strong exception for the map).
56  *
57  * When `StoreHash` is true, 32 bits of the hash are stored alongside the
58  * values. It can improve the performance during lookups if the `KeyEqual`
59  * function takes time (if it engenders a cache-miss for example) as we then
60  * compare the stored hashes before comparing the keys. When
61  * `pxr_tsl::rh::power_of_two_growth_policy` is used as `GrowthPolicy`, it may also
62  * speed-up the rehash process as we can avoid to recalculate the hash. When it
63  * is detected that storing the hash will not incur any memory penalty due to
64  * alignment (i.e. `sizeof(pxr_tsl::detail_robin_hash::bucket_entry<ValueType,
65  * true>) == sizeof(pxr_tsl::detail_robin_hash::bucket_entry<ValueType, false>)`)
66  * and `pxr_tsl::rh::power_of_two_growth_policy` is used, the hash will be stored
67  * even if `StoreHash` is false so that we can speed-up the rehash (but it will
68  * not be used on lookups unless `StoreHash` is true).
69  *
70  * `GrowthPolicy` defines how the map grows and consequently how a hash value is
71  * mapped to a bucket. By default the map uses
72  * `pxr_tsl::rh::power_of_two_growth_policy`. This policy keeps the number of
73  * buckets to a power of two and uses a mask to map the hash to a bucket instead
74  * of the slow modulo. Other growth policies are available and you may define
75  * your own growth policy, check `pxr_tsl::rh::power_of_two_growth_policy` for the
76  * interface.
77  *
78  * `std::pair<Key, T>` must be swappable.
79  *
80  * `Key` and `T` must be copy and/or move constructible.
81  *
82  * If the destructor of `Key` or `T` throws an exception, the behaviour of the
83  * class is undefined.
84  *
85  * Iterators invalidation:
86  * - clear, operator=, reserve, rehash: always invalidate the iterators.
87  * - insert, emplace, emplace_hint, operator[]: if there is an effective
88  * insert, invalidate the iterators.
89  * - erase: always invalidate the iterators.
90  */
91 template <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>>
96 class robin_map {
97  private:
98  template <typename 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;
139  using hasher = typename ht::hasher;
140  using key_equal = typename ht::key_equal;
142  using reference = typename ht::reference;
144  using pointer = typename ht::pointer;
146  using iterator = typename ht::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,
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,
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 
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>
259  return m_ht.emplace_hint(hint, std::forward<P>(value));
260  }
261 
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>
287  return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
288  }
289 
290  template <class M>
292  return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
293  }
294 
295  /**
296  * Due to the way elements are stored, emplace will need to move or copy the
297  * key-value once. The method is equivalent to
298  * insert(value_type(std::forward<Args>(args)...));
299  *
300  * Mainly here for compatibility with the std::unordered_map interface.
301  */
302  template <class... Args>
303  std::pair<iterator, bool> emplace(Args&&... args) {
304  return m_ht.emplace(std::forward<Args>(args)...);
305  }
306 
307  /**
308  * Due to the way elements are stored, emplace_hint will need to move or copy
309  * the key-value once. The method is equivalent to insert(hint,
310  * value_type(std::forward<Args>(args)...));
311  *
312  * Mainly here for compatibility with the std::unordered_map interface.
313  */
314  template <class... 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>
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); }
343  return m_ht.erase(first, last);
344  }
345  size_type erase(const key_type& key) { return m_ht.erase(key); }
346 
347  /**
348  * Use the hash value 'precalculated_hash' instead of hashing the key. The
349  * hash value should be the same as hash_function()(key). Useful to speed-up
350  * the lookup to the value if you already have the hash.
351  */
352  size_type erase(const key_type& key, std::size_t precalculated_hash) {
353  return m_ht.erase(key, precalculated_hash);
354  }
355 
356  /**
357  * This overload only participates in the overload resolution if the typedef
358  * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
359  * to Key.
360  */
361  template <
362  class K, class KE = KeyEqual,
364  size_type erase(const K& key) {
365  return m_ht.erase(key);
366  }
367 
368  /**
369  * @copydoc erase(const K& key)
370  *
371  * Use the hash value 'precalculated_hash' instead of hashing the key. The
372  * hash value should be the same as hash_function()(key). Useful to speed-up
373  * the lookup to the value if you already have the hash.
374  */
375  template <
376  class K, class KE = KeyEqual,
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 
389  /**
390  * Use the hash value 'precalculated_hash' instead of hashing the key. The
391  * hash value should be the same as hash_function()(key). Useful to speed-up
392  * the lookup if you already have the hash.
393  */
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 
400  /**
401  * @copydoc at(const Key& key, std::size_t precalculated_hash)
402  */
403  const T& at(const Key& key, std::size_t precalculated_hash) const {
404  return m_ht.at(key, precalculated_hash);
405  }
406 
407  /**
408  * This overload only participates in the overload resolution if the typedef
409  * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
410  * to Key.
411  */
412  template <
413  class K, class KE = KeyEqual,
415  T& at(const K& key) {
416  return m_ht.at(key);
417  }
418 
419  /**
420  * @copydoc at(const K& key)
421  *
422  * Use the hash value 'precalculated_hash' instead of hashing the key. The
423  * hash value should be the same as hash_function()(key). Useful to speed-up
424  * the lookup if you already have the hash.
425  */
426  template <
427  class K, class KE = KeyEqual,
429  T& at(const K& key, std::size_t precalculated_hash) {
430  return m_ht.at(key, precalculated_hash);
431  }
432 
433  /**
434  * @copydoc at(const K& key)
435  */
436  template <
437  class K, class KE = KeyEqual,
439  const T& at(const K& key) const {
440  return m_ht.at(key);
441  }
442 
443  /**
444  * @copydoc at(const K& key, std::size_t precalculated_hash)
445  */
446  template <
447  class K, class KE = KeyEqual,
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 
458  /**
459  * Use the hash value 'precalculated_hash' instead of hashing the key. The
460  * hash value should be the same as hash_function()(key). Useful to speed-up
461  * the lookup if you already have the hash.
462  */
463  size_type count(const Key& key, std::size_t precalculated_hash) const {
464  return m_ht.count(key, precalculated_hash);
465  }
466 
467  /**
468  * This overload only participates in the overload resolution if the typedef
469  * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
470  * to Key.
471  */
472  template <
473  class K, class KE = KeyEqual,
475  size_type count(const K& key) const {
476  return m_ht.count(key);
477  }
478 
479  /**
480  * @copydoc count(const K& key) const
481  *
482  * Use the hash value 'precalculated_hash' instead of hashing the key. The
483  * hash value should be the same as hash_function()(key). Useful to speed-up
484  * the lookup if you already have the hash.
485  */
486  template <
487  class K, class KE = KeyEqual,
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 
495  /**
496  * Use the hash value 'precalculated_hash' instead of hashing the key. The
497  * hash value should be the same as hash_function()(key). Useful to speed-up
498  * the lookup if you already have the hash.
499  */
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 
506  /**
507  * @copydoc find(const Key& key, std::size_t precalculated_hash)
508  */
509  const_iterator find(const Key& key, std::size_t precalculated_hash) const {
510  return m_ht.find(key, precalculated_hash);
511  }
512 
513  /**
514  * This overload only participates in the overload resolution if the typedef
515  * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
516  * to Key.
517  */
518  template <
519  class K, class KE = KeyEqual,
521  iterator find(const K& key) {
522  return m_ht.find(key);
523  }
524 
525  /**
526  * @copydoc find(const K& key)
527  *
528  * Use the hash value 'precalculated_hash' instead of hashing the key. The
529  * hash value should be the same as hash_function()(key). Useful to speed-up
530  * the lookup if you already have the hash.
531  */
532  template <
533  class K, class KE = KeyEqual,
535  iterator find(const K& key, std::size_t precalculated_hash) {
536  return m_ht.find(key, precalculated_hash);
537  }
538 
539  /**
540  * @copydoc find(const K& key)
541  */
542  template <
543  class K, class KE = KeyEqual,
545  const_iterator find(const K& key) const {
546  return m_ht.find(key);
547  }
548 
549  /**
550  * @copydoc find(const K& key)
551  *
552  * Use the hash value 'precalculated_hash' instead of hashing the key. The
553  * hash value should be the same as hash_function()(key). Useful to speed-up
554  * the lookup if you already have the hash.
555  */
556  template <
557  class K, class KE = KeyEqual,
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 
565  /**
566  * Use the hash value 'precalculated_hash' instead of hashing the key. The
567  * hash value should be the same as hash_function()(key). Useful to speed-up
568  * the lookup if you already have the hash.
569  */
570  bool contains(const Key& key, std::size_t precalculated_hash) const {
571  return m_ht.contains(key, precalculated_hash);
572  }
573 
574  /**
575  * This overload only participates in the overload resolution if the typedef
576  * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
577  * to Key.
578  */
579  template <
580  class K, class KE = KeyEqual,
582  bool contains(const K& key) const {
583  return m_ht.contains(key);
584  }
585 
586  /**
587  * @copydoc contains(const K& key) const
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  template <
594  class K, class KE = KeyEqual,
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 
604  /**
605  * Use the hash value 'precalculated_hash' instead of hashing the key. The
606  * hash value should be the same as hash_function()(key). Useful to speed-up
607  * the lookup if you already have the hash.
608  */
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 
618  /**
619  * @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
620  */
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 
626  /**
627  * This overload only participates in the overload resolution if the typedef
628  * KeyEqual::is_transparent exists. If so, K must be hashable and comparable
629  * to Key.
630  */
631  template <
632  class K, class KE = KeyEqual,
634  std::pair<iterator, iterator> equal_range(const K& key) {
635  return m_ht.equal_range(key);
636  }
637 
638  /**
639  * @copydoc equal_range(const K& key)
640  *
641  * Use the hash value 'precalculated_hash' instead of hashing the key. The
642  * hash value should be the same as hash_function()(key). Useful to speed-up
643  * the lookup if you already have the hash.
644  */
645  template <
646  class K, class KE = KeyEqual,
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 
653  /**
654  * @copydoc equal_range(const K& key)
655  */
656  template <
657  class K, class KE = KeyEqual,
659  std::pair<const_iterator, const_iterator> equal_range(const K& key) const {
660  return m_ht.equal_range(key);
661  }
662 
663  /**
664  * @copydoc equal_range(const K& key, std::size_t precalculated_hash)
665  */
666  template <
667  class K, class KE = KeyEqual,
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 
688  /**
689  * Set the `min_load_factor` to `ml`. When the `load_factor` of the map goes
690  * below `min_load_factor` after some erase operations, the map will be
691  * shrunk when an insertion occurs. The erase method itself never shrinks
692  * the map.
693  *
694  * The default value of `min_load_factor` is 0.0f, the map never shrinks by
695  * default.
696  */
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 
713  /**
714  * Convert a const_iterator to an iterator.
715  */
717  return m_ht.mutable_iterator(pos);
718  }
719 
720  /**
721  * Serialize the map through the `serializer` parameter.
722  *
723  * The `serializer` parameter must be a function object that supports the
724  * following call:
725  * - `template<typename U> void operator()(const U& value);` where the types
726  * `std::int16_t`, `std::uint32_t`, `std::uint64_t`, `float` and
727  * `std::pair<Key, T>` must be supported for U.
728  *
729  * The implementation leaves binary compatibility (endianness, IEEE 754 for
730  * floats, ...) of the types it serializes in the hands of the `Serializer`
731  * function object if compatibility is required.
732  */
733  template <class Serializer>
734  void serialize(Serializer& serializer) const {
735  m_ht.serialize(serializer);
736  }
737 
738  /**
739  * Deserialize a previously serialized map through the `deserializer`
740  * parameter.
741  *
742  * The `deserializer` parameter must be a function object that supports the
743  * following call:
744  * - `template<typename U> U operator()();` where the types `std::int16_t`,
745  * `std::uint32_t`, `std::uint64_t`, `float` and `std::pair<Key, T>` must be
746  * supported for U.
747  *
748  * If the deserialized hash map type is hash compatible with the serialized
749  * map, the deserialization process can be sped up by setting
750  * `hash_compatible` to true. To be hash compatible, the Hash, KeyEqual and
751  * GrowthPolicy must behave the same way than the ones used on the serialized
752  * map and the StoreHash must have the same value. The `std::size_t` must also
753  * be of the same size as the one on the platform used to serialize the map.
754  * If these criteria are not met, the behaviour is undefined with
755  * `hash_compatible` sets to true.
756  *
757  * The behaviour is undefined if the type `Key` and `T` of the `robin_map` are
758  * not the same as the types used during serialization.
759  *
760  * The implementation leaves binary compatibility (endianness, IEEE 754 for
761  * floats, size of int, ...) of the types it deserializes in the hands of the
762  * `Deserializer` function object if compatibility is required.
763  */
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 
799 /**
800  * Same as `pxr_tsl::robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash,
801  * pxr_tsl::rh::prime_growth_policy>`.
802  */
803 template <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>
807 using robin_pg_map = robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash,
809 
810 } // end namespace pxr_tsl
811 
813 
814 #endif
iterator insert(const_iterator hint, P &&value)
Definition: robin_map.h:258
bool contains(const Key &key) const
Definition: robin_map.h:563
iterator end() noexcept
Definition: robin_map.h:222
GLint first
Definition: glcorearb.h:405
iterator emplace_hint(const_iterator hint, Args &&...args)
Definition: robin_hash.h:800
T & at(const K &key, std::size_t precalculated_hash)
Definition: robin_map.h:429
iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args)
Definition: robin_hash.h:812
size_type erase(const key_type &key, std::size_t precalculated_hash)
Definition: robin_map.h:352
robin_map(InputIt first, InputIt last, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition: robin_map.h:184
void deserialize(Deserializer &deserializer, bool hash_compatible)
Definition: robin_hash.h:1113
void clear() noexcept
Definition: robin_map.h:236
std::pair< iterator, bool > insert(P &&value)
Definition: robin_map.h:244
size_type erase(const K &key, std::size_t precalculated_hash)
Definition: robin_map.h:378
iterator find(const Key &key, std::size_t precalculated_hash)
Definition: robin_map.h:500
iterator emplace_hint(const_iterator hint, Args &&...args)
Definition: robin_map.h:315
const T & at(const K &key, std::size_t precalculated_hash) const
Definition: robin_map.h:449
iterator erase(const_iterator pos)
Definition: robin_map.h:341
STATIC_INLINE size_t Hash(const char *s, size_t len)
Definition: farmhash.h:2038
std::pair< iterator, bool > insert_or_assign(K &&key, M &&obj)
Definition: robin_hash.h:773
std::pair< iterator, bool > emplace(Args &&...args)
Definition: robin_map.h:303
std::pair< iterator, iterator > equal_range(const K &key)
Definition: robin_map.h:634
bool contains(const K &key, std::size_t precalculated_hash) const
Definition: robin_map.h:596
hasher hash_function() const
Definition: robin_map.h:706
bool contains(const K &key) const
Definition: robin_map.h:582
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
Definition: robin_map.h:609
GLsizei const GLfloat * value
Definition: glcorearb.h:824
const_iterator find(const Key &key, std::size_t precalculated_hash) const
Definition: robin_map.h:509
iterator mutable_iterator(const_iterator pos)
Definition: robin_map.h:716
float max_load_factor() const
Definition: robin_map.h:686
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
Definition: robin_map.h:648
T & operator[](const Key &key)
Definition: robin_map.h:453
size_type count(const Key &key) const
Definition: robin_map.h:456
void swap(robin_hash &other)
Definition: robin_hash.h:924
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:188
size_type erase(const key_type &key)
Definition: robin_map.h:345
void serialize(Serializer &serializer) const
Definition: robin_hash.h:1108
const_iterator find(const K &key, std::size_t precalculated_hash) const
Definition: robin_map.h:559
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
std::pair< iterator, iterator > equal_range(const K &key)
Definition: robin_hash.h:1025
bool contains(const K &key) const
Definition: robin_hash.h:1015
iterator find(const K &key, std::size_t precalculated_hash)
Definition: robin_map.h:535
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
Definition: robin_map.h:621
size_type count(const Key &key, std::size_t precalculated_hash) const
Definition: robin_map.h:463
size_type erase(const K &key)
Definition: robin_map.h:364
std::pair< iterator, bool > emplace(Args &&...args)
Definition: robin_hash.h:795
size_type bucket_count() const
Definition: robin_map.h:677
iterator insert_hint(const_iterator hint, P &&value)
Definition: robin_hash.h:743
allocator_type get_allocator() const
Definition: robin_map.h:213
iterator find(const Key &key)
Definition: robin_map.h:493
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition: robin_map.h:659
size_type count(const K &key) const
Definition: robin_hash.h:981
friend bool operator==(const robin_map &lhs, const robin_map &rhs)
Definition: robin_map.h:773
const T & at(const K &key) const
Definition: robin_map.h:439
const_iterator cend() const noexcept
Definition: robin_hash.h:708
void serialize(Serializer &serializer) const
Definition: robin_map.h:734
robin_map(std::initializer_list< value_type > init, size_type bucket_count, const Allocator &alloc)
Definition: robin_map.h:194
typename ht::key_type key_type
Definition: robin_map.h:134
robin_map(size_type bucket_count, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition: robin_map.h:155
iterator try_emplace(const_iterator hint, const key_type &k, Args &&...args)
Definition: robin_map.h:330
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
Definition: robin_map.h:669
std::pair< iterator, bool > insert_or_assign(const key_type &k, M &&obj)
Definition: robin_map.h:276
typename ht::value_type value_type
Definition: robin_map.h:136
robin_map(size_type bucket_count, const Allocator &alloc)
Definition: robin_map.h:160
void reserve(size_type count_)
Definition: robin_map.h:701
void max_load_factor(float ml)
Definition: robin_map.h:698
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:170
T & at(const K &key)
Definition: robin_map.h:415
const_iterator find(const Key &key) const
Definition: robin_map.h:504
GLuint GLuint end
Definition: glcorearb.h:475
const_iterator cend() const noexcept
Definition: robin_map.h:224
iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj)
Definition: robin_map.h:286
const_iterator find(const K &key) const
Definition: robin_map.h:545
iterator insert(const_iterator hint, value_type &&value)
Definition: robin_map.h:262
std::pair< iterator, bool > insert(P &&value)
Definition: robin_hash.h:738
size_type max_size() const noexcept
Definition: robin_map.h:231
void swap(robin_map &other)
Definition: robin_map.h:382
size_type max_size() const noexcept
Definition: robin_hash.h:719
std::pair< iterator, bool > try_emplace(K &&key, Args &&...args)
Definition: robin_hash.h:805
void rehash(size_type count_)
Definition: robin_map.h:700
friend bool operator!=(const robin_map &lhs, const robin_map &rhs)
Definition: robin_map.h:789
bool empty() const noexcept
Definition: robin_map.h:229
size_type size() const noexcept
Definition: robin_map.h:230
const_iterator cbegin() const noexcept
Definition: robin_hash.h:695
void insert(std::initializer_list< value_type > ilist)
Definition: robin_map.h:271
size_type count(const K &key) const
Definition: robin_map.h:475
robin_map(const Allocator &alloc)
Definition: robin_map.h:166
iterator find(const K &key)
Definition: robin_map.h:521
static robin_map deserialize(Deserializer &deserializer, bool hash_compatible=false)
Definition: robin_map.h:765
robin_map(size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition: robin_map.h:163
std::pair< iterator, bool > insert(value_type &&value)
Definition: robin_map.h:248
std::pair< iterator, bool > try_emplace(const key_type &k, Args &&...args)
Definition: robin_map.h:320
bool contains(const Key &key, std::size_t precalculated_hash) const
Definition: robin_map.h:570
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
const_iterator begin() const noexcept
Definition: robin_map.h:219
iterator mutable_iterator(const_iterator pos)
Definition: robin_hash.h:1103
std::pair< iterator, bool > try_emplace(key_type &&k, Args &&...args)
Definition: robin_map.h:325
iterator erase(iterator pos)
Definition: robin_map.h:340
float min_load_factor() const
Definition: robin_map.h:685
T & at(const Key &key, std::size_t precalculated_hash)
Definition: robin_map.h:394
std::pair< iterator, iterator > equal_range(const Key &key)
Definition: robin_map.h:600
const T & at(const Key &key) const
Definition: robin_map.h:398
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
friend void swap(robin_map &lhs, robin_map &rhs)
Definition: robin_map.h:793
std::pair< iterator, bool > insert(const value_type &value)
Definition: robin_map.h:238
T & operator[](Key &&key)
Definition: robin_map.h:454
const_iterator end() const noexcept
Definition: robin_map.h:223
T & at(const Key &key)
Definition: robin_map.h:387
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
iterator erase(const_iterator first, const_iterator last)
Definition: robin_map.h:342
void insert(InputIt first, InputIt last)
Definition: robin_map.h:267
void min_load_factor(float ml)
Definition: robin_map.h:697
**If you just want to fire and args
Definition: thread.h:609
size_type size() const noexcept
Definition: robin_hash.h:717
const_iterator cbegin() const noexcept
Definition: robin_map.h:220
robin_map & operator=(std::initializer_list< value_type > ilist)
Definition: robin_map.h:204
Definition: core.h:1131
U::value_type & at(const K &key)
Definition: robin_hash.h:946
const T & at(const Key &key, std::size_t precalculated_hash) const
Definition: robin_map.h:403
size_type count(const K &key, std::size_t precalculated_hash) const
Definition: robin_map.h:489
robin_map(std::initializer_list< value_type > init, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition: robin_map.h:199
float load_factor() const
Definition: robin_map.h:683
allocator_type get_allocator() const
Definition: robin_hash.h:677
robin_map(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc)
Definition: robin_map.h:179
iterator try_emplace(const_iterator hint, key_type &&k, Args &&...args)
Definition: robin_map.h:335
iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj)
Definition: robin_map.h:291
key_equal key_eq() const
Definition: robin_map.h:707
size_type max_bucket_count() const
Definition: robin_map.h:678
std::pair< iterator, bool > insert_or_assign(key_type &&k, M &&obj)
Definition: robin_map.h:281
type
Definition: core.h:1059
iterator begin() noexcept
Definition: robin_map.h:218
iterator insert(const_iterator hint, const value_type &value)
Definition: robin_map.h:252
std::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition: robin_map.h:614
robin_map< Key, T, Hash, KeyEqual, Allocator, StoreHash, pxr_tsl::rh::prime_growth_policy > robin_pg_map
Definition: robin_map.h:808