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 
39 PXR_NAMESPACE_OPEN_SCOPE
40 
41 namespace pxr_tsl {
42 
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>
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 
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 
812 PXR_NAMESPACE_CLOSE_SCOPE
813 
814 #endif
void serialize(Serializer &serializer) const
Serialize the map through the serializer parameter.
Definition: robin_map.h:734
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
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
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
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
Grow the hash table by using prime numbers as bucket count.
void min_load_factor(float ml)
Set the min_load_factor to ml.
Definition: robin_map.h:697
Implementation of a hash map using open-addressing and the robin hood hashing algorithm with backward...
Definition: robin_map.h:96
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
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
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
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
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
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
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 K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_map.h:415
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< 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
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
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, 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
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
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_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
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 Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_map.h:463
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
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
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
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
MIT License.
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
iterator mutable_iterator(const_iterator pos)
Convert a const_iterator to an iterator.
Definition: robin_map.h:716
robin_map< Key, T, Hash, KeyEqual, Allocator, StoreHash, pxr_tsl::rh::prime_growth_policy > robin_pg_map
Same as pxr_tsl::robin_map<Key, T, Hash, KeyEqual, Allocator, StoreHash, pxr_tsl::rh::prime_growth_po...
Definition: robin_map.h:808
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
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
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