robin_hash.h
Go to the documentation of this file.
1 
24 #ifndef TSL_ROBIN_HASH_H
25 #define TSL_ROBIN_HASH_H
26 
27 #include <algorithm>
28 #include <cassert>
29 #include <cmath>
30 #include <cstddef>
31 #include <cstdint>
32 #include <exception>
33 #include <iterator>
34 #include <limits>
35 #include <memory>
36 #include <new>
37 #include <stdexcept>
38 #include <tuple>
39 #include <type_traits>
40 #include <utility>
41 #include <vector>
42 
43 #include "robin_growth_policy.h"
44 
45 namespace tsl {
46 
47 namespace detail_robin_hash {
48 
49 template <typename T>
50 struct make_void {
51  using type = void;
52 };
53 
54 template <typename T, typename = void>
56 
57 template <typename T>
59  typename make_void<typename T::is_transparent>::type>
60  : std::true_type {};
61 
62 template <typename U>
64 
65 template <std::size_t GrowthFactor>
67  : std::true_type {};
68 
69 // Only available in C++17, we need to be compatible with C++11
70 template <class T>
71 const T& clamp(const T& v, const T& lo, const T& hi) {
72  return std::min(hi, std::max(lo, v));
73 }
74 
75 template <typename T, typename U>
76 static T numeric_cast(U value,
77  const char* error_message = "numeric_cast() failed.") {
78  T ret = static_cast<T>(value);
79  if (static_cast<U>(ret) != value) {
80  TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message);
81  }
82 
83  const bool is_same_signedness =
84  (std::is_unsigned<T>::value && std::is_unsigned<U>::value) ||
85  (std::is_signed<T>::value && std::is_signed<U>::value);
86  if (!is_same_signedness && (ret < T{}) != (value < U{})) {
87  TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message);
88  }
89 
90  TSL_RH_UNUSED(error_message);
91 
92  return ret;
93 }
94 
95 template <class T, class Deserializer>
96 static T deserialize_value(Deserializer& deserializer) {
97  // MSVC < 2017 is not conformant, circumvent the problem by removing the
98  // template keyword
99 #if defined(_MSC_VER) && _MSC_VER < 1910
100  return deserializer.Deserializer::operator()<T>();
101 #else
102  return deserializer.Deserializer::template operator()<T>();
103 #endif
104 }
105 
111 using slz_size_type = std::uint64_t;
112 static_assert(std::numeric_limits<slz_size_type>::max() >=
113  std::numeric_limits<std::size_t>::max(),
114  "slz_size_type must be >= std::size_t");
115 
116 using truncated_hash_type = std::uint32_t;
117 
122 template <bool StoreHash>
124  public:
125  bool bucket_hash_equal(std::size_t /*hash*/) const noexcept { return true; }
126 
127  truncated_hash_type truncated_hash() const noexcept { return 0; }
128 
129  protected:
130  void set_hash(truncated_hash_type /*hash*/) noexcept {}
131 };
132 
133 template <>
134 class bucket_entry_hash<true> {
135  public:
136  bool bucket_hash_equal(std::size_t hash) const noexcept {
137  return m_hash == truncated_hash_type(hash);
138  }
139 
140  truncated_hash_type truncated_hash() const noexcept { return m_hash; }
141 
142  protected:
143  void set_hash(truncated_hash_type hash) noexcept {
144  m_hash = truncated_hash_type(hash);
145  }
146 
147  private:
149 };
150 
169 template <typename ValueType, bool StoreHash>
170 class bucket_entry : public bucket_entry_hash<StoreHash> {
172 
173  public:
174  using value_type = ValueType;
175  using distance_type = std::int16_t;
176 
177  bucket_entry() noexcept
178  : bucket_hash(),
180  m_last_bucket(false) {
181  tsl_rh_assert(empty());
182  }
183 
184  bucket_entry(bool last_bucket) noexcept
185  : bucket_hash(),
188  tsl_rh_assert(empty());
189  }
190 
191  bucket_entry(const bucket_entry& other) noexcept(
192  std::is_nothrow_copy_constructible<value_type>::value)
193  : bucket_hash(other),
196  if (!other.empty()) {
197  ::new (static_cast<void*>(std::addressof(m_value)))
198  value_type(other.value());
199  m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
200  }
201  tsl_rh_assert(empty() == other.empty());
202  }
203 
209  bucket_entry(bucket_entry&& other) noexcept(
210  std::is_nothrow_move_constructible<value_type>::value)
211  : bucket_hash(std::move(other)),
214  if (!other.empty()) {
215  ::new (static_cast<void*>(std::addressof(m_value)))
216  value_type(std::move(other.value()));
217  m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
218  }
219  tsl_rh_assert(empty() == other.empty());
220  }
221 
222  bucket_entry& operator=(const bucket_entry& other) noexcept(
223  std::is_nothrow_copy_constructible<value_type>::value) {
224  if (this != &other) {
225  clear();
226 
227  bucket_hash::operator=(other);
228  if (!other.empty()) {
229  ::new (static_cast<void*>(std::addressof(m_value)))
230  value_type(other.value());
231  }
232 
233  m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket;
234  m_last_bucket = other.m_last_bucket;
235  }
236 
237  return *this;
238  }
239 
240  bucket_entry& operator=(bucket_entry&&) = delete;
241 
242  ~bucket_entry() noexcept { clear(); }
243 
244  void clear() noexcept {
245  if (!empty()) {
246  destroy_value();
248  }
249  }
250 
251  bool empty() const noexcept {
253  }
254 
255  value_type& value() noexcept {
256  tsl_rh_assert(!empty());
257 #if defined(__cplusplus) && __cplusplus >= 201703L
258  return *std::launder(
259  reinterpret_cast<value_type*>(std::addressof(m_value)));
260 #else
261  return *reinterpret_cast<value_type*>(std::addressof(m_value));
262 #endif
263  }
264 
265  const value_type& value() const noexcept {
266  tsl_rh_assert(!empty());
267 #if defined(__cplusplus) && __cplusplus >= 201703L
268  return *std::launder(
269  reinterpret_cast<const value_type*>(std::addressof(m_value)));
270 #else
271  return *reinterpret_cast<const value_type*>(std::addressof(m_value));
272 #endif
273  }
274 
277  }
278 
279  bool last_bucket() const noexcept { return m_last_bucket; }
280 
281  void set_as_last_bucket() noexcept { m_last_bucket = true; }
282 
283  template <typename... Args>
285  truncated_hash_type hash,
286  Args&&... value_type_args) {
288  tsl_rh_assert(empty());
289 
290  ::new (static_cast<void*>(std::addressof(m_value)))
291  value_type(std::forward<Args>(value_type_args)...);
292  this->set_hash(hash);
294 
295  tsl_rh_assert(!empty());
296  }
297 
300  tsl_rh_assert(!empty());
302 
303  using std::swap;
304  swap(value, this->value());
305  swap(dist_from_ideal_bucket, m_dist_from_ideal_bucket);
306 
307  if (StoreHash) {
308  const truncated_hash_type tmp_hash = this->truncated_hash();
309  this->set_hash(hash);
310  hash = tmp_hash;
311  } else {
312  // Avoid warning of unused variable if StoreHash is false
313  TSL_RH_UNUSED(hash);
314  }
315  }
316 
317  static truncated_hash_type truncate_hash(std::size_t hash) noexcept {
318  return truncated_hash_type(hash);
319  }
320 
321  private:
322  void destroy_value() noexcept {
323  tsl_rh_assert(!empty());
324  value().~value_type();
325  }
326 
327  public:
330  static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <=
331  std::numeric_limits<distance_type>::max() - 1,
332  "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= "
333  "std::numeric_limits<distance_type>::max() - 1.");
334 
335  private:
338  alignas(value_type) unsigned char m_value[sizeof(value_type)];
339 };
340 
360 template <class ValueType, class KeySelect, class ValueSelect, class Hash,
361  class KeyEqual, class Allocator, bool StoreHash, class GrowthPolicy>
362 class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
363  private:
364  template <typename U>
365  using has_mapped_type =
366  typename std::integral_constant<bool, !std::is_same<U, void>::value>;
367 
368  static_assert(
369  noexcept(std::declval<GrowthPolicy>().bucket_for_hash(std::size_t(0))),
370  "GrowthPolicy::bucket_for_hash must be noexcept.");
371  static_assert(noexcept(std::declval<GrowthPolicy>().clear()),
372  "GrowthPolicy::clear must be noexcept.");
373 
374  public:
375  template <bool IsConst>
377 
378  using key_type = typename KeySelect::key_type;
379  using value_type = ValueType;
380  using size_type = std::size_t;
381  using difference_type = std::ptrdiff_t;
382  using hasher = Hash;
383  using key_equal = KeyEqual;
384  using allocator_type = Allocator;
386  using const_reference = const value_type&;
387  using pointer = value_type*;
388  using const_pointer = const value_type*;
389  using iterator = robin_iterator<false>;
390  using const_iterator = robin_iterator<true>;
391 
392  private:
398  static constexpr bool STORE_HASH =
399  StoreHash ||
402  (sizeof(std::size_t) == sizeof(truncated_hash_type) ||
404  // Don't store the hash for primitive types with default hash.
405  (!std::is_arithmetic<key_type>::value ||
406  !std::is_same<Hash, std::hash<key_type>>::value));
407 
413  static constexpr bool USE_STORED_HASH_ON_LOOKUP = StoreHash;
414 
422  if (STORE_HASH && sizeof(std::size_t) == sizeof(truncated_hash_type)) {
424  return true;
426  return bucket_count == 0 ||
427  (bucket_count - 1) <=
428  std::numeric_limits<truncated_hash_type>::max();
429  } else {
431  return false;
432  }
433  }
434 
435  using bucket_entry =
438 
439  using buckets_allocator = typename std::allocator_traits<
440  allocator_type>::template rebind_alloc<bucket_entry>;
441  using buckets_container_type = std::vector<bucket_entry, buckets_allocator>;
442 
443  public:
455  template <bool IsConst>
456  class robin_iterator {
457  friend class robin_hash;
458 
459  private:
460  using bucket_entry_ptr =
461  typename std::conditional<IsConst, const bucket_entry*,
462  bucket_entry*>::type;
463 
464  robin_iterator(bucket_entry_ptr bucket) noexcept : m_bucket(bucket) {}
465 
466  public:
467  using iterator_category = std::forward_iterator_tag;
468  using value_type = const typename robin_hash::value_type;
469  using difference_type = std::ptrdiff_t;
471  using pointer = value_type*;
472 
473  robin_iterator() noexcept {}
474 
475  // Copy constructor from iterator to const_iterator.
476  template <bool TIsConst = IsConst,
477  typename std::enable_if<TIsConst>::type* = nullptr>
479  : m_bucket(other.m_bucket) {}
480 
481  robin_iterator(const robin_iterator& other) = default;
482  robin_iterator(robin_iterator&& other) = default;
483  robin_iterator& operator=(const robin_iterator& other) = default;
484  robin_iterator& operator=(robin_iterator&& other) = default;
485 
486  const typename robin_hash::key_type& key() const {
487  return KeySelect()(m_bucket->value());
488  }
489 
490  template <class U = ValueSelect,
491  typename std::enable_if<has_mapped_type<U>::value &&
492  IsConst>::type* = nullptr>
493  const typename U::value_type& value() const {
494  return U()(m_bucket->value());
495  }
496 
497  template <class U = ValueSelect,
498  typename std::enable_if<has_mapped_type<U>::value &&
499  !IsConst>::type* = nullptr>
500  typename U::value_type& value() const {
501  return U()(m_bucket->value());
502  }
503 
504  reference operator*() const { return m_bucket->value(); }
505 
506  pointer operator->() const { return std::addressof(m_bucket->value()); }
507 
509  while (true) {
510  if (m_bucket->last_bucket()) {
511  ++m_bucket;
512  return *this;
513  }
514 
515  ++m_bucket;
516  if (!m_bucket->empty()) {
517  return *this;
518  }
519  }
520  }
521 
523  robin_iterator tmp(*this);
524  ++*this;
525 
526  return tmp;
527  }
528 
529  friend bool operator==(const robin_iterator& lhs,
530  const robin_iterator& rhs) {
531  return lhs.m_bucket == rhs.m_bucket;
532  }
533 
534  friend bool operator!=(const robin_iterator& lhs,
535  const robin_iterator& rhs) {
536  return !(lhs == rhs);
537  }
538 
539  private:
541  };
542 
543  public:
544 #if defined(__cplusplus) && __cplusplus >= 201402L
545  robin_hash(size_type bucket_count, const Hash& hash, const KeyEqual& equal,
546  const Allocator& alloc,
549  : Hash(hash),
550  KeyEqual(equal),
551  GrowthPolicy(bucket_count),
554  : m_buckets_data.data()),
556  m_nb_elements(0),
557  m_grow_on_next_insert(false),
559  if (bucket_count > max_bucket_count()) {
560  TSL_RH_THROW_OR_TERMINATE(std::length_error,
561  "The map exceeds its maximum bucket count.");
562  }
563 
564  if (m_bucket_count > 0) {
565  tsl_rh_assert(!m_buckets_data.empty());
566  m_buckets_data.back().set_as_last_bucket();
567  }
568 
571  }
572 #else
573 
583  robin_hash(size_type bucket_count, const Hash& hash, const KeyEqual& equal,
584  const Allocator& alloc,
587  : Hash(hash),
588  KeyEqual(equal),
589  GrowthPolicy(bucket_count),
590  m_buckets_data(alloc),
593  m_nb_elements(0),
594  m_grow_on_next_insert(false),
596  if (bucket_count > max_bucket_count()) {
597  TSL_RH_THROW_OR_TERMINATE(std::length_error,
598  "The map exceeds its maximum bucket count.");
599  }
600 
601  if (m_bucket_count > 0) {
603  m_buckets = m_buckets_data.data();
604 
605  tsl_rh_assert(!m_buckets_data.empty());
606  m_buckets_data.back().set_as_last_bucket();
607  }
608 
611  }
612 #endif
613 
614  robin_hash(const robin_hash& other)
615  : Hash(other),
616  KeyEqual(other),
617  GrowthPolicy(other),
620  : m_buckets_data.data()),
628 
629  robin_hash(robin_hash&& other) noexcept(
630  std::is_nothrow_move_constructible<
631  Hash>::value&& std::is_nothrow_move_constructible<KeyEqual>::value&&
632  std::is_nothrow_move_constructible<GrowthPolicy>::value&&
633  std::is_nothrow_move_constructible<buckets_container_type>::value)
634  : Hash(std::move(static_cast<Hash&>(other))),
635  KeyEqual(std::move(static_cast<KeyEqual&>(other))),
636  GrowthPolicy(std::move(static_cast<GrowthPolicy&>(other))),
637  m_buckets_data(std::move(other.m_buckets_data)),
639  : m_buckets_data.data()),
647  other.clear_and_shrink();
648  }
649 
650  robin_hash& operator=(const robin_hash& other) {
651  if (&other != this) {
652  Hash::operator=(other);
653  KeyEqual::operator=(other);
654  GrowthPolicy::operator=(other);
655 
658  : m_buckets_data.data();
661 
665 
668  }
669 
670  return *this;
671  }
672 
674  other.swap(*this);
675  other.clear_and_shrink();
676 
677  return *this;
678  }
679 
681  return m_buckets_data.get_allocator();
682  }
683 
684  /*
685  * Iterators
686  */
687  iterator begin() noexcept {
688  std::size_t i = 0;
689  while (i < m_bucket_count && m_buckets[i].empty()) {
690  i++;
691  }
692 
693  return iterator(m_buckets + i);
694  }
695 
696  const_iterator begin() const noexcept { return cbegin(); }
697 
698  const_iterator cbegin() const noexcept {
699  std::size_t i = 0;
700  while (i < m_bucket_count && m_buckets[i].empty()) {
701  i++;
702  }
703 
704  return const_iterator(m_buckets + i);
705  }
706 
707  iterator end() noexcept { return iterator(m_buckets + m_bucket_count); }
708 
709  const_iterator end() const noexcept { return cend(); }
710 
711  const_iterator cend() const noexcept {
713  }
714 
715  /*
716  * Capacity
717  */
718  bool empty() const noexcept { return m_nb_elements == 0; }
719 
720  size_type size() const noexcept { return m_nb_elements; }
721 
722  size_type max_size() const noexcept { return m_buckets_data.max_size(); }
723 
724  /*
725  * Modifiers
726  */
727  void clear() noexcept {
728  if (m_min_load_factor > 0.0f) {
730  } else {
731  for (auto& bucket : m_buckets_data) {
732  bucket.clear();
733  }
734 
735  m_nb_elements = 0;
736  m_grow_on_next_insert = false;
737  }
738  }
739 
740  template <typename P>
741  std::pair<iterator, bool> insert(P&& value) {
742  return insert_impl(KeySelect()(value), std::forward<P>(value));
743  }
744 
745  template <typename P>
747  if (hint != cend() &&
748  compare_keys(KeySelect()(*hint), KeySelect()(value))) {
749  return mutable_iterator(hint);
750  }
751 
752  return insert(std::forward<P>(value)).first;
753  }
754 
755  template <class InputIt>
756  void insert(InputIt first, InputIt last) {
757  if (std::is_base_of<
758  std::forward_iterator_tag,
759  typename std::iterator_traits<InputIt>::iterator_category>::value) {
760  const auto nb_elements_insert = std::distance(first, last);
761  const size_type nb_free_buckets = m_load_threshold - size();
763 
764  if (nb_elements_insert > 0 &&
765  nb_free_buckets < size_type(nb_elements_insert)) {
766  reserve(size() + size_type(nb_elements_insert));
767  }
768  }
769 
770  for (; first != last; ++first) {
771  insert(*first);
772  }
773  }
774 
775  template <class K, class M>
776  std::pair<iterator, bool> insert_or_assign(K&& key, M&& obj) {
777  auto it = try_emplace(std::forward<K>(key), std::forward<M>(obj));
778  if (!it.second) {
779  it.first.value() = std::forward<M>(obj);
780  }
781 
782  return it;
783  }
784 
785  template <class K, class M>
786  iterator insert_or_assign(const_iterator hint, K&& key, M&& obj) {
787  if (hint != cend() && compare_keys(KeySelect()(*hint), key)) {
788  auto it = mutable_iterator(hint);
789  it.value() = std::forward<M>(obj);
790 
791  return it;
792  }
793 
794  return insert_or_assign(std::forward<K>(key), std::forward<M>(obj)).first;
795  }
796 
797  template <class... Args>
798  std::pair<iterator, bool> emplace(Args&&... args) {
799  return insert(value_type(std::forward<Args>(args)...));
800  }
801 
802  template <class... Args>
803  iterator emplace_hint(const_iterator hint, Args&&... args) {
804  return insert_hint(hint, value_type(std::forward<Args>(args)...));
805  }
806 
807  template <class K, class... Args>
808  std::pair<iterator, bool> try_emplace(K&& key, Args&&... args) {
809  return insert_impl(key, std::piecewise_construct,
810  std::forward_as_tuple(std::forward<K>(key)),
811  std::forward_as_tuple(std::forward<Args>(args)...));
812  }
813 
814  template <class K, class... Args>
815  iterator try_emplace_hint(const_iterator hint, K&& key, Args&&... args) {
816  if (hint != cend() && compare_keys(KeySelect()(*hint), key)) {
817  return mutable_iterator(hint);
818  }
819 
820  return try_emplace(std::forward<K>(key), std::forward<Args>(args)...).first;
821  }
822 
823  void erase_fast(iterator pos) {
824  erase_from_bucket(pos);
825  }
826 
832  erase_from_bucket(pos);
833 
839  if (pos.m_bucket->empty()) {
840  ++pos;
841  }
842 
843  return pos;
844  }
845 
847 
849  if (first == last) {
850  return mutable_iterator(first);
851  }
852 
853  auto first_mutable = mutable_iterator(first);
854  auto last_mutable = mutable_iterator(last);
855  for (auto it = first_mutable.m_bucket; it != last_mutable.m_bucket; ++it) {
856  if (!it->empty()) {
857  it->clear();
858  m_nb_elements--;
859  }
860  }
861 
862  if (last_mutable == end()) {
864  return end();
865  }
866 
867  /*
868  * Backward shift on the values which come after the deleted values.
869  * We try to move the values closer to their ideal bucket.
870  */
871  std::size_t icloser_bucket =
872  static_cast<std::size_t>(first_mutable.m_bucket - m_buckets);
873  std::size_t ito_move_closer_value =
874  static_cast<std::size_t>(last_mutable.m_bucket - m_buckets);
875  tsl_rh_assert(ito_move_closer_value > icloser_bucket);
876 
877  const std::size_t ireturn_bucket =
878  ito_move_closer_value -
879  std::min(
880  ito_move_closer_value - icloser_bucket,
881  std::size_t(
882  m_buckets[ito_move_closer_value].dist_from_ideal_bucket()));
883 
884  while (ito_move_closer_value < m_bucket_count &&
885  m_buckets[ito_move_closer_value].dist_from_ideal_bucket() > 0) {
886  icloser_bucket =
887  ito_move_closer_value -
888  std::min(
889  ito_move_closer_value - icloser_bucket,
890  std::size_t(
891  m_buckets[ito_move_closer_value].dist_from_ideal_bucket()));
892 
893  tsl_rh_assert(m_buckets[icloser_bucket].empty());
894  const distance_type new_distance = distance_type(
895  m_buckets[ito_move_closer_value].dist_from_ideal_bucket() -
896  (ito_move_closer_value - icloser_bucket));
897  m_buckets[icloser_bucket].set_value_of_empty_bucket(
898  new_distance, m_buckets[ito_move_closer_value].truncated_hash(),
899  std::move(m_buckets[ito_move_closer_value].value()));
900  m_buckets[ito_move_closer_value].clear();
901 
902  ++icloser_bucket;
903  ++ito_move_closer_value;
904  }
905 
907 
908  return iterator(m_buckets + ireturn_bucket);
909  }
910 
911  template <class K>
912  size_type erase(const K& key) {
913  return erase(key, hash_key(key));
914  }
915 
916  template <class K>
917  size_type erase(const K& key, std::size_t hash) {
918  auto it = find(key, hash);
919  if (it != end()) {
920  erase_from_bucket(it);
921  return 1;
922  } else {
923  return 0;
924  }
925  }
926 
927  void swap(robin_hash& other) {
928  using std::swap;
929 
930  swap(static_cast<Hash&>(*this), static_cast<Hash&>(other));
931  swap(static_cast<KeyEqual&>(*this), static_cast<KeyEqual&>(other));
932  swap(static_cast<GrowthPolicy&>(*this), static_cast<GrowthPolicy&>(other));
934  swap(m_buckets, other.m_buckets);
942  }
943 
944  /*
945  * Lookup
946  */
947  template <class K, class U = ValueSelect,
948  typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>
949  typename U::value_type& at(const K& key) {
950  return at(key, hash_key(key));
951  }
952 
953  template <class K, class U = ValueSelect,
954  typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>
955  typename U::value_type& at(const K& key, std::size_t hash) {
956  return const_cast<typename U::value_type&>(
957  static_cast<const robin_hash*>(this)->at(key, hash));
958  }
959 
960  template <class K, class U = ValueSelect,
961  typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>
962  const typename U::value_type& at(const K& key) const {
963  return at(key, hash_key(key));
964  }
965 
966  template <class K, class U = ValueSelect,
967  typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>
968  const typename U::value_type& at(const K& key, std::size_t hash) const {
969  auto it = find(key, hash);
970  if (it != cend()) {
971  return it.value();
972  } else {
973  TSL_RH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find key.");
974  }
975  }
976 
977  template <class K, class U = ValueSelect,
978  typename std::enable_if<has_mapped_type<U>::value>::type* = nullptr>
979  typename U::value_type& operator[](K&& key) {
980  return try_emplace(std::forward<K>(key)).first.value();
981  }
982 
983  template <class K>
984  size_type count(const K& key) const {
985  return count(key, hash_key(key));
986  }
987 
988  template <class K>
989  size_type count(const K& key, std::size_t hash) const {
990  if (find(key, hash) != cend()) {
991  return 1;
992  } else {
993  return 0;
994  }
995  }
996 
997  template <class K>
998  iterator find(const K& key) {
999  return find_impl(key, hash_key(key));
1000  }
1001 
1002  template <class K>
1003  iterator find(const K& key, std::size_t hash) {
1004  return find_impl(key, hash);
1005  }
1006 
1007  template <class K>
1008  const_iterator find(const K& key) const {
1009  return find_impl(key, hash_key(key));
1010  }
1011 
1012  template <class K>
1013  const_iterator find(const K& key, std::size_t hash) const {
1014  return find_impl(key, hash);
1015  }
1016 
1017  template <class K>
1018  bool contains(const K& key) const {
1019  return contains(key, hash_key(key));
1020  }
1021 
1022  template <class K>
1023  bool contains(const K& key, std::size_t hash) const {
1024  return count(key, hash) != 0;
1025  }
1026 
1027  template <class K>
1028  std::pair<iterator, iterator> equal_range(const K& key) {
1029  return equal_range(key, hash_key(key));
1030  }
1031 
1032  template <class K>
1033  std::pair<iterator, iterator> equal_range(const K& key, std::size_t hash) {
1034  iterator it = find(key, hash);
1035  return std::make_pair(it, (it == end()) ? it : std::next(it));
1036  }
1037 
1038  template <class K>
1039  std::pair<const_iterator, const_iterator> equal_range(const K& key) const {
1040  return equal_range(key, hash_key(key));
1041  }
1042 
1043  template <class K>
1044  std::pair<const_iterator, const_iterator> equal_range(
1045  const K& key, std::size_t hash) const {
1046  const_iterator it = find(key, hash);
1047  return std::make_pair(it, (it == cend()) ? it : std::next(it));
1048  }
1049 
1050  /*
1051  * Bucket interface
1052  */
1054 
1056  return std::min(GrowthPolicy::max_bucket_count(),
1057  m_buckets_data.max_size());
1058  }
1059 
1060  /*
1061  * Hash policy
1062  */
1063  float load_factor() const {
1064  if (bucket_count() == 0) {
1065  return 0;
1066  }
1067 
1068  return float(m_nb_elements) / float(bucket_count());
1069  }
1070 
1071  float min_load_factor() const { return m_min_load_factor; }
1072 
1073  float max_load_factor() const { return m_max_load_factor; }
1074 
1075  void min_load_factor(float ml) {
1077  float(MAXIMUM_MIN_LOAD_FACTOR));
1078  }
1079 
1080  void max_load_factor(float ml) {
1082  float(MAXIMUM_MAX_LOAD_FACTOR));
1085  }
1086 
1087  void rehash(size_type count_) {
1088  count_ = std::max(count_,
1089  size_type(std::ceil(float(size()) / max_load_factor())));
1090  rehash_impl(count_);
1091  }
1092 
1093  void reserve(size_type count_) {
1094  rehash(size_type(std::ceil(float(count_) / max_load_factor())));
1095  }
1096 
1097  /*
1098  * Observers
1099  */
1100  hasher hash_function() const { return static_cast<const Hash&>(*this); }
1101 
1102  key_equal key_eq() const { return static_cast<const KeyEqual&>(*this); }
1103 
1104  /*
1105  * Other
1106  */
1108  return iterator(const_cast<bucket_entry*>(pos.m_bucket));
1109  }
1110 
1111  template <class Serializer>
1112  void serialize(Serializer& serializer) const {
1114  }
1115 
1116  template <class Deserializer>
1117  void deserialize(Deserializer& deserializer, bool hash_compatible) {
1118  deserialize_impl(deserializer, hash_compatible);
1119  }
1120 
1121  private:
1122  template <class K>
1123  std::size_t hash_key(const K& key) const {
1124  return Hash::operator()(key);
1125  }
1126 
1127  template <class K1, class K2>
1128  bool compare_keys(const K1& key1, const K2& key2) const {
1129  return KeyEqual::operator()(key1, key2);
1130  }
1131 
1132  std::size_t bucket_for_hash(std::size_t hash) const {
1133  const std::size_t bucket = GrowthPolicy::bucket_for_hash(hash);
1134  tsl_rh_assert(bucket < m_bucket_count ||
1135  (bucket == 0 && m_bucket_count == 0));
1136 
1137  return bucket;
1138  }
1139 
1140  template <class U = GrowthPolicy,
1141  typename std::enable_if<is_power_of_two_policy<U>::value>::type* =
1142  nullptr>
1143  std::size_t next_bucket(std::size_t index) const noexcept {
1144  tsl_rh_assert(index < bucket_count());
1145 
1146  return (index + 1) & this->m_mask;
1147  }
1148 
1149  template <class U = GrowthPolicy,
1150  typename std::enable_if<!is_power_of_two_policy<U>::value>::type* =
1151  nullptr>
1152  std::size_t next_bucket(std::size_t index) const noexcept {
1153  tsl_rh_assert(index < bucket_count());
1154 
1155  index++;
1156  return (index != bucket_count()) ? index : 0;
1157  }
1158 
1159  template <class K>
1160  iterator find_impl(const K& key, std::size_t hash) {
1161  return mutable_iterator(
1162  static_cast<const robin_hash*>(this)->find(key, hash));
1163  }
1164 
1165  template <class K>
1166  const_iterator find_impl(const K& key, std::size_t hash) const {
1167  std::size_t ibucket = bucket_for_hash(hash);
1168  distance_type dist_from_ideal_bucket = 0;
1169 
1170  while (dist_from_ideal_bucket <=
1171  m_buckets[ibucket].dist_from_ideal_bucket()) {
1172  if (TSL_RH_LIKELY(
1174  m_buckets[ibucket].bucket_hash_equal(hash)) &&
1175  compare_keys(KeySelect()(m_buckets[ibucket].value()), key))) {
1176  return const_iterator(m_buckets + ibucket);
1177  }
1178 
1179  ibucket = next_bucket(ibucket);
1180  dist_from_ideal_bucket++;
1181  }
1182 
1183  return cend();
1184  }
1185 
1187  pos.m_bucket->clear();
1188  m_nb_elements--;
1189 
1197  std::size_t previous_ibucket =
1198  static_cast<std::size_t>(pos.m_bucket - m_buckets);
1199  std::size_t ibucket = next_bucket(previous_ibucket);
1200 
1201  while (m_buckets[ibucket].dist_from_ideal_bucket() > 0) {
1202  tsl_rh_assert(m_buckets[previous_ibucket].empty());
1203 
1204  const distance_type new_distance =
1205  distance_type(m_buckets[ibucket].dist_from_ideal_bucket() - 1);
1206  m_buckets[previous_ibucket].set_value_of_empty_bucket(
1207  new_distance, m_buckets[ibucket].truncated_hash(),
1208  std::move(m_buckets[ibucket].value()));
1209  m_buckets[ibucket].clear();
1210 
1211  previous_ibucket = ibucket;
1212  ibucket = next_bucket(ibucket);
1213  }
1215  }
1216 
1217  template <class K, class... Args>
1218  std::pair<iterator, bool> insert_impl(const K& key,
1219  Args&&... value_type_args) {
1220  const std::size_t hash = hash_key(key);
1221 
1222  std::size_t ibucket = bucket_for_hash(hash);
1223  distance_type dist_from_ideal_bucket = 0;
1224 
1225  while (dist_from_ideal_bucket <=
1226  m_buckets[ibucket].dist_from_ideal_bucket()) {
1227  if ((!USE_STORED_HASH_ON_LOOKUP ||
1228  m_buckets[ibucket].bucket_hash_equal(hash)) &&
1229  compare_keys(KeySelect()(m_buckets[ibucket].value()), key)) {
1230  return std::make_pair(iterator(m_buckets + ibucket), false);
1231  }
1232 
1233  ibucket = next_bucket(ibucket);
1234  dist_from_ideal_bucket++;
1235  }
1236 
1237  while (rehash_on_extreme_load(dist_from_ideal_bucket)) {
1238  ibucket = bucket_for_hash(hash);
1239  dist_from_ideal_bucket = 0;
1240 
1241  while (dist_from_ideal_bucket <=
1242  m_buckets[ibucket].dist_from_ideal_bucket()) {
1243  ibucket = next_bucket(ibucket);
1244  dist_from_ideal_bucket++;
1245  }
1246  }
1247 
1248  if (m_buckets[ibucket].empty()) {
1250  dist_from_ideal_bucket, bucket_entry::truncate_hash(hash),
1251  std::forward<Args>(value_type_args)...);
1252  } else {
1253  insert_value(ibucket, dist_from_ideal_bucket,
1255  std::forward<Args>(value_type_args)...);
1256  }
1257 
1258  m_nb_elements++;
1259  /*
1260  * The value will be inserted in ibucket in any case, either because it was
1261  * empty or by stealing the bucket (robin hood).
1262  */
1263  return std::make_pair(iterator(m_buckets + ibucket), true);
1264  }
1265 
1266  template <class... Args>
1267  void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket,
1268  truncated_hash_type hash, Args&&... value_type_args) {
1269  value_type value(std::forward<Args>(value_type_args)...);
1270  insert_value_impl(ibucket, dist_from_ideal_bucket, hash, value);
1271  }
1272 
1273  void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket,
1274  truncated_hash_type hash, value_type&& value) {
1275  insert_value_impl(ibucket, dist_from_ideal_bucket, hash, value);
1276  }
1277 
1278  /*
1279  * We don't use `value_type&& value` as last argument due to a bug in MSVC
1280  * when `value_type` is a pointer, The compiler is not able to see the
1281  * difference between `std::string*` and `std::string*&&` resulting in a
1282  * compilation error.
1283  *
1284  * The `value` will be in a moved state at the end of the function.
1285  */
1286  void insert_value_impl(std::size_t ibucket,
1287  distance_type dist_from_ideal_bucket,
1288  truncated_hash_type hash, value_type& value) {
1289  tsl_rh_assert(dist_from_ideal_bucket >
1290  m_buckets[ibucket].dist_from_ideal_bucket());
1291  m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, hash,
1292  value);
1293  ibucket = next_bucket(ibucket);
1294  dist_from_ideal_bucket++;
1295 
1296  while (!m_buckets[ibucket].empty()) {
1297  if (dist_from_ideal_bucket >
1298  m_buckets[ibucket].dist_from_ideal_bucket()) {
1299  if (dist_from_ideal_bucket >
1305  m_grow_on_next_insert = true;
1306  }
1307 
1308  m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket,
1309  hash, value);
1310  }
1311 
1312  ibucket = next_bucket(ibucket);
1313  dist_from_ideal_bucket++;
1314  }
1315 
1316  m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, hash,
1317  std::move(value));
1318  }
1319 
1320  void rehash_impl(size_type count_) {
1321  robin_hash new_table(count_, static_cast<Hash&>(*this),
1322  static_cast<KeyEqual&>(*this), get_allocator(),
1324  tsl_rh_assert(size() <= new_table.m_load_threshold);
1325 
1326  const bool use_stored_hash =
1328  for (auto& bucket : m_buckets_data) {
1329  if (bucket.empty()) {
1330  continue;
1331  }
1332 
1333  const std::size_t hash =
1334  use_stored_hash ? bucket.truncated_hash()
1335  : new_table.hash_key(KeySelect()(bucket.value()));
1336 
1337  new_table.insert_value_on_rehash(new_table.bucket_for_hash(hash), 0,
1339  std::move(bucket.value()));
1340  }
1341 
1342  new_table.m_nb_elements = m_nb_elements;
1343  new_table.swap(*this);
1344  }
1345 
1346  void clear_and_shrink() noexcept {
1347  GrowthPolicy::clear();
1348  m_buckets_data.clear();
1350  m_bucket_count = 0;
1351  m_nb_elements = 0;
1352  m_load_threshold = 0;
1353  m_grow_on_next_insert = false;
1355  }
1356 
1357  void insert_value_on_rehash(std::size_t ibucket,
1358  distance_type dist_from_ideal_bucket,
1359  truncated_hash_type hash, value_type&& value) {
1360  while (true) {
1361  if (dist_from_ideal_bucket >
1362  m_buckets[ibucket].dist_from_ideal_bucket()) {
1363  if (m_buckets[ibucket].empty()) {
1364  m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket,
1365  hash, std::move(value));
1366  return;
1367  } else {
1368  m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket,
1369  hash, value);
1370  }
1371  }
1372 
1373  dist_from_ideal_bucket++;
1374  ibucket = next_bucket(ibucket);
1375  }
1376  }
1377 
1385  bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) {
1386  if (m_grow_on_next_insert ||
1387  curr_dist_from_ideal_bucket >
1389  size() >= m_load_threshold) {
1390  rehash_impl(GrowthPolicy::next_bucket_count());
1391  m_grow_on_next_insert = false;
1392 
1393  return true;
1394  }
1395 
1398  if (m_min_load_factor != 0.0f && load_factor() < m_min_load_factor) {
1399  reserve(size() + 1);
1400 
1401  return true;
1402  }
1403  }
1404 
1405  return false;
1406  }
1407 
1408  template <class Serializer>
1409  void serialize_impl(Serializer& serializer) const {
1411  serializer(version);
1412 
1413  // Indicate if the truncated hash of each bucket is stored. Use a
1414  // std::int16_t instead of a bool to avoid the need for the serializer to
1415  // support an extra 'bool' type.
1416  const std::int16_t hash_stored_for_bucket =
1417  static_cast<std::int16_t>(STORE_HASH);
1418  serializer(hash_stored_for_bucket);
1419 
1420  const slz_size_type nb_elements = m_nb_elements;
1421  serializer(nb_elements);
1422 
1423  const slz_size_type bucket_count = m_buckets_data.size();
1425 
1426  const float min_load_factor = m_min_load_factor;
1428 
1429  const float max_load_factor = m_max_load_factor;
1431 
1432  for (const bucket_entry& bucket : m_buckets_data) {
1433  if (bucket.empty()) {
1434  const std::int16_t empty_bucket =
1436  serializer(empty_bucket);
1437  } else {
1438  const std::int16_t dist_from_ideal_bucket =
1439  bucket.dist_from_ideal_bucket();
1440  serializer(dist_from_ideal_bucket);
1441  if (STORE_HASH) {
1442  const std::uint32_t truncated_hash = bucket.truncated_hash();
1443  serializer(truncated_hash);
1444  }
1445  serializer(bucket.value());
1446  }
1447  }
1448  }
1449 
1450  template <class Deserializer>
1451  void deserialize_impl(Deserializer& deserializer, bool hash_compatible) {
1452  tsl_rh_assert(m_buckets_data.empty()); // Current hash table must be empty
1453 
1454  const slz_size_type version =
1455  deserialize_value<slz_size_type>(deserializer);
1456  // For now we only have one version of the serialization protocol.
1457  // If it doesn't match there is a problem with the file.
1458  if (version != SERIALIZATION_PROTOCOL_VERSION) {
1459  TSL_RH_THROW_OR_TERMINATE(std::runtime_error,
1460  "Can't deserialize the ordered_map/set. "
1461  "The protocol version header is invalid.");
1462  }
1463 
1464  const bool hash_stored_for_bucket =
1465  deserialize_value<std::int16_t>(deserializer) ? true : false;
1466  if (hash_compatible && STORE_HASH != hash_stored_for_bucket) {
1468  std::runtime_error,
1469  "Can't deserialize a map with a different StoreHash "
1470  "than the one used during the serialization when "
1471  "hash compatibility is used");
1472  }
1473 
1474  const slz_size_type nb_elements =
1475  deserialize_value<slz_size_type>(deserializer);
1476  const slz_size_type bucket_count_ds =
1477  deserialize_value<slz_size_type>(deserializer);
1478  const float min_load_factor = deserialize_value<float>(deserializer);
1479  const float max_load_factor = deserialize_value<float>(deserializer);
1480 
1484  std::runtime_error,
1485  "Invalid min_load_factor. Check that the serializer "
1486  "and deserializer support floats correctly as they "
1487  "can be converted implicitly to ints.");
1488  }
1489 
1493  std::runtime_error,
1494  "Invalid max_load_factor. Check that the serializer "
1495  "and deserializer support floats correctly as they "
1496  "can be converted implicitly to ints.");
1497  }
1498 
1499  this->min_load_factor(min_load_factor);
1500  this->max_load_factor(max_load_factor);
1501 
1502  if (bucket_count_ds == 0) {
1503  tsl_rh_assert(nb_elements == 0);
1504  return;
1505  }
1506 
1507  if (!hash_compatible) {
1508  reserve(numeric_cast<size_type>(nb_elements,
1509  "Deserialized nb_elements is too big."));
1510  for (slz_size_type ibucket = 0; ibucket < bucket_count_ds; ibucket++) {
1511  const distance_type dist_from_ideal_bucket =
1512  deserialize_value<std::int16_t>(deserializer);
1513  if (dist_from_ideal_bucket !=
1515  if (hash_stored_for_bucket) {
1516  TSL_RH_UNUSED(deserialize_value<std::uint32_t>(deserializer));
1517  }
1518 
1519  insert(deserialize_value<value_type>(deserializer));
1520  }
1521  }
1522 
1523  tsl_rh_assert(nb_elements == size());
1524  } else {
1525  m_bucket_count = numeric_cast<size_type>(
1526  bucket_count_ds, "Deserialized bucket_count is too big.");
1527 
1528  GrowthPolicy::operator=(GrowthPolicy(m_bucket_count));
1529  // GrowthPolicy should not modify the bucket count we got from
1530  // deserialization
1531  if (m_bucket_count != bucket_count_ds) {
1532  TSL_RH_THROW_OR_TERMINATE(std::runtime_error,
1533  "The GrowthPolicy is not the same even "
1534  "though hash_compatible is true.");
1535  }
1536 
1537  m_nb_elements = numeric_cast<size_type>(
1538  nb_elements, "Deserialized nb_elements is too big.");
1540  m_buckets = m_buckets_data.data();
1541 
1542  for (bucket_entry& bucket : m_buckets_data) {
1543  const distance_type dist_from_ideal_bucket =
1544  deserialize_value<std::int16_t>(deserializer);
1545  if (dist_from_ideal_bucket !=
1547  truncated_hash_type truncated_hash = 0;
1548  if (hash_stored_for_bucket) {
1549  tsl_rh_assert(hash_stored_for_bucket);
1550  truncated_hash = deserialize_value<std::uint32_t>(deserializer);
1551  }
1552 
1553  bucket.set_value_of_empty_bucket(
1554  dist_from_ideal_bucket, truncated_hash,
1555  deserialize_value<value_type>(deserializer));
1556  }
1557  }
1558 
1559  if (!m_buckets_data.empty()) {
1560  m_buckets_data.back().set_as_last_bucket();
1561  }
1562  }
1563  }
1564 
1565  public:
1567 
1568  static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.5f;
1569  static constexpr float MINIMUM_MAX_LOAD_FACTOR = 0.2f;
1570  static constexpr float MAXIMUM_MAX_LOAD_FACTOR = 0.95f;
1571 
1572  static constexpr float DEFAULT_MIN_LOAD_FACTOR = 0.0f;
1573  static constexpr float MINIMUM_MIN_LOAD_FACTOR = 0.0f;
1574  static constexpr float MAXIMUM_MIN_LOAD_FACTOR = 0.15f;
1575 
1577  "MINIMUM_MAX_LOAD_FACTOR should be < MAXIMUM_MAX_LOAD_FACTOR");
1579  "MINIMUM_MIN_LOAD_FACTOR should be < MAXIMUM_MIN_LOAD_FACTOR");
1581  "MAXIMUM_MIN_LOAD_FACTOR should be < MINIMUM_MAX_LOAD_FACTOR");
1582 
1583  private:
1588 
1594  static bucket_entry empty_bucket(true);
1595  tsl_rh_assert(empty_bucket.empty());
1596  return &empty_bucket;
1597  }
1598 
1599  private:
1601 
1612 
1618 
1620 
1622 
1625 
1627 
1636 };
1637 
1638 } // namespace detail_robin_hash
1639 
1640 } // namespace tsl
1641 
1642 #endif
tsl::detail_robin_hash::bucket_entry::bucket_entry
bucket_entry(const bucket_entry &other) noexcept(std::is_nothrow_copy_constructible< value_type >::value)
Definition: robin_hash.h:191
tsl::detail_robin_hash::robin_hash::equal_range
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition: robin_hash.h:1039
tsl
Definition: robin_growth_policy.h:84
tsl::detail_robin_hash::is_power_of_two_policy
Definition: robin_hash.h:63
tsl::detail_robin_hash::robin_hash::erase_fast
void erase_fast(iterator pos)
Definition: robin_hash.h:823
tsl::detail_robin_hash::robin_hash::contains
bool contains(const K &key) const
Definition: robin_hash.h:1018
tsl::detail_robin_hash::robin_hash::m_load_threshold
size_type m_load_threshold
Definition: robin_hash.h:1621
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::const_pointer
const value_type * const_pointer
Definition: robin_hash.h:388
tsl::detail_robin_hash::robin_hash::reserve
void reserve(size_type count_)
Definition: robin_hash.h:1093
tsl::detail_robin_hash::robin_hash::hash_function
hasher hash_function() const
Definition: robin_hash.h:1100
tsl::detail_robin_hash::robin_hash::size
size_type size() const noexcept
Definition: robin_hash.h:720
tsl::detail_robin_hash::robin_hash::max_load_factor
float max_load_factor() const
Definition: robin_hash.h:1073
tsl::detail_robin_hash::bucket_entry::dist_from_ideal_bucket
distance_type dist_from_ideal_bucket() const noexcept
Definition: robin_hash.h:275
tsl::detail_robin_hash::robin_hash::DEFAULT_MIN_LOAD_FACTOR
static constexpr float DEFAULT_MIN_LOAD_FACTOR
Definition: robin_hash.h:1572
tsl::detail_robin_hash::robin_hash::has_mapped_type
typename std::integral_constant< bool, !std::is_same< U, void >::value > has_mapped_type
Definition: robin_hash.h:366
tsl::detail_robin_hash::robin_hash::emplace
std::pair< iterator, bool > emplace(Args &&... args)
Definition: robin_hash.h:798
tsl::detail_robin_hash::make_void::type
void type
Definition: robin_hash.h:51
tsl::detail_robin_hash::make_void
Definition: robin_hash.h:50
robin_growth_policy.h
tsl::detail_robin_hash::robin_hash::insert_or_assign
iterator insert_or_assign(const_iterator hint, K &&key, M &&obj)
Definition: robin_hash.h:786
tsl::detail_robin_hash::bucket_entry::set_as_last_bucket
void set_as_last_bucket() noexcept
Definition: robin_hash.h:281
tsl::detail_robin_hash::clamp
const T & clamp(const T &v, const T &lo, const T &hi)
Definition: robin_hash.h:71
tsl::detail_robin_hash::robin_hash::erase
size_type erase(const K &key, std::size_t hash)
Definition: robin_hash.h:917
tsl::detail_robin_hash::robin_hash::STORE_HASH
static constexpr bool STORE_HASH
Definition: robin_hash.h:398
tsl::detail_robin_hash::robin_hash::at
const U::value_type & at(const K &key, std::size_t hash) const
Definition: robin_hash.h:968
tsl::detail_robin_hash::robin_hash::erase
size_type erase(const K &key)
Definition: robin_hash.h:912
tsl::detail_robin_hash::robin_hash::robin_iterator::robin_iterator
robin_iterator(bucket_entry_ptr bucket) noexcept
Definition: robin_hash.h:464
std::swap
void swap(linb::any &lhs, linb::any &rhs) noexcept
Definition: any.hpp:452
tsl::detail_robin_hash::bucket_entry::last_bucket
bool last_bucket() const noexcept
Definition: robin_hash.h:279
tsl::detail_robin_hash::robin_hash::bucket_for_hash
std::size_t bucket_for_hash(std::size_t hash) const
Definition: robin_hash.h:1132
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::difference_type
std::ptrdiff_t difference_type
Definition: robin_hash.h:381
tsl::detail_robin_hash::robin_hash::m_try_shrink_on_next_insert
bool m_try_shrink_on_next_insert
Definition: robin_hash.h:1635
tsl::detail_robin_hash::bucket_entry::swap_with_value_in_bucket
void swap_with_value_in_bucket(distance_type &dist_from_ideal_bucket, truncated_hash_type &hash, value_type &value)
Definition: robin_hash.h:298
tsl::detail_robin_hash::bucket_entry_hash::bucket_hash_equal
bool bucket_hash_equal(std::size_t) const noexcept
Definition: robin_hash.h:125
kitti-run-seq.f
string f
Definition: kitti-run-seq.py:12
tsl::detail_robin_hash::bucket_entry::bucket_entry
bucket_entry() noexcept
Definition: robin_hash.h:177
tsl::detail_robin_hash::bucket_entry::~bucket_entry
~bucket_entry() noexcept
Definition: robin_hash.h:242
tsl::detail_robin_hash::robin_hash::empty
bool empty() const noexcept
Definition: robin_hash.h:718
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::size_type
std::size_t size_type
Definition: robin_hash.h:380
tsl::detail_robin_hash::bucket_entry_hash< true >::m_hash
truncated_hash_type m_hash
Definition: robin_hash.h:148
TSL_RH_LIKELY
#define TSL_RH_LIKELY(exp)
Definition: robin_growth_policy.h:79
tsl::detail_robin_hash::bucket_entry_hash::set_hash
void set_hash(truncated_hash_type) noexcept
Definition: robin_hash.h:130
tsl::detail_robin_hash::robin_hash::contains
bool contains(const K &key, std::size_t hash) const
Definition: robin_hash.h:1023
tsl::detail_robin_hash::robin_hash::USE_STORED_HASH_ON_REHASH
static bool USE_STORED_HASH_ON_REHASH(size_type bucket_count)
Definition: robin_hash.h:421
tsl::detail_robin_hash::robin_hash::m_buckets
bucket_entry * m_buckets
Definition: robin_hash.h:1611
tsl::detail_robin_hash::robin_hash::serialize
void serialize(Serializer &serializer) const
Definition: robin_hash.h:1112
tsl::detail_robin_hash::bucket_entry::m_last_bucket
bool m_last_bucket
Definition: robin_hash.h:337
testing::internal::false_type
bool_constant< false > false_type
Definition: gtest.h:2724
tsl::detail_robin_hash::robin_hash::robin_iterator::difference_type
std::ptrdiff_t difference_type
Definition: robin_hash.h:469
tsl::detail_robin_hash::robin_hash::m_grow_on_next_insert
bool m_grow_on_next_insert
Definition: robin_hash.h:1626
tsl::detail_robin_hash::robin_hash::robin_iterator::value
U::value_type & value() const
Definition: robin_hash.h:500
tsl::detail_robin_hash::robin_hash::robin_iterator::robin_iterator
robin_iterator(const robin_iterator<!TIsConst > &other) noexcept
Definition: robin_hash.h:478
testing::internal::true_type
bool_constant< true > true_type
Definition: gtest.h:2725
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::pointer
value_type * pointer
Definition: robin_hash.h:387
serializer
Definition: robin-map/tests/utils.h:349
tsl::detail_robin_hash::robin_hash::robin_iterator::bucket_entry_ptr
typename std::conditional< IsConst, const bucket_entry *, bucket_entry * >::type bucket_entry_ptr
Definition: robin_hash.h:462
tsl::detail_robin_hash::robin_hash::operator=
robin_hash & operator=(robin_hash &&other)
Definition: robin_hash.h:673
tsl::detail_robin_hash::robin_hash::compare_keys
bool compare_keys(const K1 &key1, const K2 &key2) const
Definition: robin_hash.h:1128
tsl::detail_robin_hash::robin_hash::find_impl
const_iterator find_impl(const K &key, std::size_t hash) const
Definition: robin_hash.h:1166
tsl::detail_robin_hash::robin_hash::at
U::value_type & at(const K &key)
Definition: robin_hash.h:949
tsl::detail_robin_hash::robin_hash::max_size
size_type max_size() const noexcept
Definition: robin_hash.h:722
tsl::detail_robin_hash::robin_hash::robin_iterator::operator*
reference operator*() const
Definition: robin_hash.h:504
tsl::detail_robin_hash::robin_hash::hash_key
std::size_t hash_key(const K &key) const
Definition: robin_hash.h:1123
tsl::detail_robin_hash::robin_hash::m_min_load_factor
float m_min_load_factor
Definition: robin_hash.h:1623
std::allocator
tsl::detail_robin_hash::robin_hash::insert_hint
iterator insert_hint(const_iterator hint, P &&value)
Definition: robin_hash.h:746
tsl::detail_robin_hash::robin_hash::find
const_iterator find(const K &key) const
Definition: robin_hash.h:1008
tsl::detail_robin_hash::bucket_entry::value_type
ValueType value_type
Definition: robin_hash.h:174
tsl::detail_robin_hash::robin_hash::begin
const_iterator begin() const noexcept
Definition: robin_hash.h:696
tsl_rh_assert
#define tsl_rh_assert(expr)
Definition: robin_growth_policy.h:51
tsl::detail_robin_hash::robin_hash::erase_from_bucket
void erase_from_bucket(iterator pos)
Definition: robin_hash.h:1186
tsl::detail_robin_hash::robin_hash::clear
void clear() noexcept
Definition: robin_hash.h:727
tsl::detail_robin_hash::bucket_entry::m_value
unsigned char m_value[sizeof(value_type)]
Definition: robin_hash.h:338
tsl::detail_robin_hash::robin_hash::rehash_on_extreme_load
bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket)
Definition: robin_hash.h:1385
tsl::detail_robin_hash::robin_hash::robin_iterator
Definition: robin_hash.h:376
tsl::detail_robin_hash::deserialize_value
static T deserialize_value(Deserializer &deserializer)
Definition: robin_hash.h:96
tsl::detail_robin_hash::robin_hash::robin_iterator::operator++
robin_iterator operator++(int)
Definition: robin_hash.h:522
tsl::detail_robin_hash::robin_hash::find
const_iterator find(const K &key, std::size_t hash) const
Definition: robin_hash.h:1013
tsl::detail_robin_hash::robin_hash::insert_value
void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, truncated_hash_type hash, value_type &&value)
Definition: robin_hash.h:1273
tsl::detail_robin_hash::bucket_entry::m_dist_from_ideal_bucket
distance_type m_dist_from_ideal_bucket
Definition: robin_hash.h:333
tsl::detail_robin_hash::robin_hash::find
iterator find(const K &key, std::size_t hash)
Definition: robin_hash.h:1003
tsl::detail_robin_hash::robin_hash::clear_and_shrink
void clear_and_shrink() noexcept
Definition: robin_hash.h:1346
tsl::detail_robin_hash::bucket_entry::distance_type
std::int16_t distance_type
Definition: robin_hash.h:175
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::value_type
Key value_type
Definition: robin_hash.h:379
tsl::detail_robin_hash::robin_hash::find
iterator find(const K &key)
Definition: robin_hash.h:998
tsl::detail_robin_hash::robin_hash::insert_impl
std::pair< iterator, bool > insert_impl(const K &key, Args &&... value_type_args)
Definition: robin_hash.h:1218
tsl::detail_robin_hash::robin_hash::SERIALIZATION_PROTOCOL_VERSION
static const slz_size_type SERIALIZATION_PROTOCOL_VERSION
Definition: robin_hash.h:1587
tsl::detail_robin_hash::robin_hash::cbegin
const_iterator cbegin() const noexcept
Definition: robin_hash.h:698
tsl::detail_robin_hash::bucket_entry::bucket_hash
bucket_entry_hash< StoreHash > bucket_hash
Definition: robin_hash.h:171
tsl::detail_robin_hash::robin_hash::rehash
void rehash(size_type count_)
Definition: robin_hash.h:1087
tsl::detail_robin_hash::robin_hash::operator[]
U::value_type & operator[](K &&key)
Definition: robin_hash.h:979
tsl::detail_robin_hash::robin_hash::count
size_type count(const K &key) const
Definition: robin_hash.h:984
tsl::detail_robin_hash::robin_hash::robin_iterator::operator!=
friend bool operator!=(const robin_iterator &lhs, const robin_iterator &rhs)
Definition: robin_hash.h:534
tsl::detail_robin_hash::robin_hash::static_empty_bucket_ptr
bucket_entry * static_empty_bucket_ptr() noexcept
Definition: robin_hash.h:1593
tsl::detail_robin_hash::robin_hash::insert
void insert(InputIt first, InputIt last)
Definition: robin_hash.h:756
tsl::detail_robin_hash::robin_hash::robin_iterator::pointer
value_type * pointer
Definition: robin_hash.h:471
tsl::detail_robin_hash::robin_hash::MINIMUM_MAX_LOAD_FACTOR
static constexpr float MINIMUM_MAX_LOAD_FACTOR
Definition: robin_hash.h:1569
tsl::detail_robin_hash::has_is_transparent
Definition: robin_hash.h:55
tsl::detail_robin_hash::robin_hash::DEFAULT_INIT_BUCKETS_SIZE
static const size_type DEFAULT_INIT_BUCKETS_SIZE
Definition: robin_hash.h:1566
tsl::detail_robin_hash::robin_hash::cend
const_iterator cend() const noexcept
Definition: robin_hash.h:711
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::key_equal
std::equal_to< Key > key_equal
Definition: robin_hash.h:383
TSL_RH_THROW_OR_TERMINATE
#define TSL_RH_THROW_OR_TERMINATE(ex, msg)
Definition: robin_growth_policy.h:72
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::reference
value_type & reference
Definition: robin_hash.h:385
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::hasher
std::hash< Key > hasher
Definition: robin_hash.h:382
tsl::detail_robin_hash::robin_hash::m_max_load_factor
float m_max_load_factor
Definition: robin_hash.h:1624
tsl::detail_robin_hash::bucket_entry::operator=
bucket_entry & operator=(const bucket_entry &other) noexcept(std::is_nothrow_copy_constructible< value_type >::value)
Definition: robin_hash.h:222
tsl::detail_robin_hash::robin_hash::robin_iterator::value_type
const typename robin_hash::value_type value_type
Definition: robin_hash.h:468
tsl::detail_robin_hash::robin_hash::erase
iterator erase(iterator pos)
Definition: robin_hash.h:831
tsl::detail_robin_hash::truncated_hash_type
std::uint32_t truncated_hash_type
Definition: robin_hash.h:116
tsl::detail_robin_hash::robin_hash
Definition: robin_hash.h:362
tsl::detail_robin_hash::robin_hash::serialize_impl
void serialize_impl(Serializer &serializer) const
Definition: robin_hash.h:1409
tsl::detail_robin_hash::robin_hash::mutable_iterator
iterator mutable_iterator(const_iterator pos)
Definition: robin_hash.h:1107
tsl::detail_robin_hash::robin_hash::count
size_type count(const K &key, std::size_t hash) const
Definition: robin_hash.h:989
tsl::detail_robin_hash::robin_hash::emplace_hint
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition: robin_hash.h:803
tsl::detail_robin_hash::robin_hash::robin_hash
robin_hash(const robin_hash &other)
Definition: robin_hash.h:614
tsl::detail_robin_hash::robin_hash::next_bucket
std::size_t next_bucket(std::size_t index) const noexcept
Definition: robin_hash.h:1143
tsl::detail_robin_hash::robin_hash::m_buckets_data
buckets_container_type m_buckets_data
Definition: robin_hash.h:1600
tsl::detail_robin_hash::bucket_entry_hash< true >::set_hash
void set_hash(truncated_hash_type hash) noexcept
Definition: robin_hash.h:143
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::buckets_allocator
typename std::allocator_traits< allocator_type >::template rebind_alloc< bucket_entry > buckets_allocator
Definition: robin_hash.h:440
tsl::detail_robin_hash::robin_hash::robin_iterator::robin_iterator
robin_iterator() noexcept
Definition: robin_hash.h:473
tsl::detail_robin_hash::robin_hash::rehash_impl
void rehash_impl(size_type count_)
Definition: robin_hash.h:1320
tsl::detail_robin_hash::robin_hash::robin_iterator::value
const U::value_type & value() const
Definition: robin_hash.h:493
tsl::detail_robin_hash::robin_hash::insert_or_assign
std::pair< iterator, bool > insert_or_assign(K &&key, M &&obj)
Definition: robin_hash.h:776
tsl::detail_robin_hash::robin_hash::robin_iterator::key
const robin_hash::key_type & key() const
Definition: robin_hash.h:486
tsl::detail_robin_hash::robin_hash::DEFAULT_MAX_LOAD_FACTOR
static constexpr float DEFAULT_MAX_LOAD_FACTOR
Definition: robin_hash.h:1568
tsl::detail_robin_hash::robin_hash::end
const_iterator end() const noexcept
Definition: robin_hash.h:709
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::const_iterator
robin_iterator< true > const_iterator
Definition: robin_hash.h:390
tsl::detail_robin_hash::robin_hash::insert_value
void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, truncated_hash_type hash, Args &&... value_type_args)
Definition: robin_hash.h:1267
tsl::detail_robin_hash::robin_hash::swap
void swap(robin_hash &other)
Definition: robin_hash.h:927
tsl::detail_robin_hash::numeric_cast
static T numeric_cast(U value, const char *error_message="numeric_cast() failed.")
Definition: robin_hash.h:76
tsl::detail_robin_hash::robin_hash::MINIMUM_MIN_LOAD_FACTOR
static constexpr float MINIMUM_MIN_LOAD_FACTOR
Definition: robin_hash.h:1573
tsl::detail_robin_hash::robin_hash::min_load_factor
float min_load_factor() const
Definition: robin_hash.h:1071
tsl::detail_robin_hash::robin_hash::equal_range
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t hash) const
Definition: robin_hash.h:1044
tsl::detail_robin_hash::robin_hash::USE_STORED_HASH_ON_LOOKUP
static constexpr bool USE_STORED_HASH_ON_LOOKUP
Definition: robin_hash.h:413
tsl::detail_robin_hash::bucket_entry::clear
void clear() noexcept
Definition: robin_hash.h:244
tsl::detail_robin_hash::robin_hash::min_load_factor
void min_load_factor(float ml)
Definition: robin_hash.h:1075
tsl::detail_robin_hash::robin_hash::max_load_factor
void max_load_factor(float ml)
Definition: robin_hash.h:1080
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::distance_type
typename bucket_entry::distance_type distance_type
Definition: robin_hash.h:437
tsl::detail_robin_hash::bucket_entry::empty
bool empty() const noexcept
Definition: robin_hash.h:251
tsl::detail_robin_hash::robin_hash::try_emplace_hint
iterator try_emplace_hint(const_iterator hint, K &&key, Args &&... args)
Definition: robin_hash.h:815
tsl::detail_robin_hash::robin_hash::robin_iterator::reference
value_type & reference
Definition: robin_hash.h:470
tsl::detail_robin_hash::bucket_entry::bucket_entry
bucket_entry(bucket_entry &&other) noexcept(std::is_nothrow_move_constructible< value_type >::value)
Definition: robin_hash.h:209
tsl::detail_robin_hash::slz_size_type
std::uint64_t slz_size_type
Definition: robin_hash.h:111
tsl::detail_robin_hash::bucket_entry_hash::truncated_hash
truncated_hash_type truncated_hash() const noexcept
Definition: robin_hash.h:127
TSL_RH_UNUSED
#define TSL_RH_UNUSED(x)
Definition: robin_growth_policy.h:82
PointMatcherSupport::Parametrizable
The superclass of classes that are constructed using generic parameters. This class provides the para...
Definition: Parametrizable.h:98
tsl::detail_robin_hash::bucket_entry_hash
Definition: robin_hash.h:123
std
tsl::detail_robin_hash::robin_hash::robin_iterator::operator->
pointer operator->() const
Definition: robin_hash.h:506
tsl::detail_robin_hash::robin_hash::end
iterator end() noexcept
Definition: robin_hash.h:707
tsl::detail_robin_hash::bucket_entry::value
const value_type & value() const noexcept
Definition: robin_hash.h:265
tsl::detail_robin_hash::bucket_entry::set_value_of_empty_bucket
void set_value_of_empty_bucket(distance_type dist_from_ideal_bucket, truncated_hash_type hash, Args &&... value_type_args)
Definition: robin_hash.h:284
tsl::detail_robin_hash::robin_hash::deserialize_impl
void deserialize_impl(Deserializer &deserializer, bool hash_compatible)
Definition: robin_hash.h:1451
tsl::rh::power_of_two_growth_policy
Definition: robin_growth_policy.h:95
tsl::detail_robin_hash::robin_hash::robin_iterator::operator++
robin_iterator & operator++()
Definition: robin_hash.h:508
tsl::detail_robin_hash::bucket_entry::truncate_hash
static truncated_hash_type truncate_hash(std::size_t hash) noexcept
Definition: robin_hash.h:317
tsl::detail_robin_hash::robin_hash::erase
iterator erase(const_iterator first, const_iterator last)
Definition: robin_hash.h:848
tsl::detail_robin_hash::robin_hash::robin_iterator::operator=
robin_iterator & operator=(const robin_iterator &other)=default
tsl::detail_robin_hash::robin_hash::robin_iterator::iterator_category
std::forward_iterator_tag iterator_category
Definition: robin_hash.h:467
tsl::detail_robin_hash::robin_hash::get_allocator
allocator_type get_allocator() const
Definition: robin_hash.h:680
tsl::detail_robin_hash::robin_hash::m_bucket_count
size_type m_bucket_count
Definition: robin_hash.h:1617
tsl::detail_robin_hash::robin_hash::MAXIMUM_MAX_LOAD_FACTOR
static constexpr float MAXIMUM_MAX_LOAD_FACTOR
Definition: robin_hash.h:1570
tsl::detail_robin_hash::robin_hash::equal_range
std::pair< iterator, iterator > equal_range(const K &key, std::size_t hash)
Definition: robin_hash.h:1033
tsl::detail_robin_hash::bucket_entry::bucket_entry
bucket_entry(bool last_bucket) noexcept
Definition: robin_hash.h:184
tsl::detail_robin_hash::robin_hash::max_bucket_count
size_type max_bucket_count() const
Definition: robin_hash.h:1055
tsl::detail_robin_hash::robin_hash::at
U::value_type & at(const K &key, std::size_t hash)
Definition: robin_hash.h:955
tsl::detail_robin_hash::bucket_entry::value
value_type & value() noexcept
Definition: robin_hash.h:255
tsl::detail_robin_hash::robin_hash::robin_iterator::m_bucket
bucket_entry_ptr m_bucket
Definition: robin_hash.h:540
tsl::detail_robin_hash::robin_hash::equal_range
std::pair< iterator, iterator > equal_range(const K &key)
Definition: robin_hash.h:1028
tsl::detail_robin_hash::robin_hash::operator=
robin_hash & operator=(const robin_hash &other)
Definition: robin_hash.h:650
tsl::detail_robin_hash::bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET
static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET
Definition: robin_hash.h:328
tsl::detail_robin_hash::robin_hash::m_nb_elements
size_type m_nb_elements
Definition: robin_hash.h:1619
tsl::detail_robin_hash::bucket_entry
Definition: robin_hash.h:170
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::key_type
typename KeySelect::key_type key_type
Definition: robin_hash.h:378
tsl::detail_robin_hash::bucket_entry::destroy_value
void destroy_value() noexcept
Definition: robin_hash.h:322
tsl::detail_robin_hash::bucket_entry_hash< true >::truncated_hash
truncated_hash_type truncated_hash() const noexcept
Definition: robin_hash.h:140
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::buckets_container_type
std::vector< bucket_entry, buckets_allocator > buckets_container_type
Definition: robin_hash.h:441
deserializer
Definition: robin-map/tests/utils.h:387
tsl::detail_robin_hash::bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT
static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT
Definition: robin_hash.h:329
tsl::detail_robin_hash::robin_hash::robin_hash
robin_hash(size_type bucket_count, const Hash &hash, const KeyEqual &equal, const Allocator &alloc, float min_load_factor=DEFAULT_MIN_LOAD_FACTOR, float max_load_factor=DEFAULT_MAX_LOAD_FACTOR)
Definition: robin_hash.h:583
tsl::detail_robin_hash::robin_hash::bucket_count
size_type bucket_count() const
Definition: robin_hash.h:1053
tsl::detail_robin_hash::robin_hash::try_emplace
std::pair< iterator, bool > try_emplace(K &&key, Args &&... args)
Definition: robin_hash.h:808
tsl::detail_robin_hash::robin_hash::find_impl
iterator find_impl(const K &key, std::size_t hash)
Definition: robin_hash.h:1160
tsl::detail_robin_hash::bucket_entry_hash< true >::bucket_hash_equal
bool bucket_hash_equal(std::size_t hash) const noexcept
Definition: robin_hash.h:136
tsl::detail_robin_hash::robin_hash::robin_iterator::operator==
friend bool operator==(const robin_iterator &lhs, const robin_iterator &rhs)
Definition: robin_hash.h:529
tsl::detail_robin_hash::robin_hash::MAXIMUM_MIN_LOAD_FACTOR
static constexpr float MAXIMUM_MIN_LOAD_FACTOR
Definition: robin_hash.h:1574
tsl::detail_robin_hash::robin_hash::begin
iterator begin() noexcept
Definition: robin_hash.h:687
tsl::detail_robin_hash::robin_hash::erase
iterator erase(const_iterator pos)
Definition: robin_hash.h:846
tsl::detail_robin_hash::robin_hash::at
const U::value_type & at(const K &key) const
Definition: robin_hash.h:962
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::iterator
robin_iterator< false > iterator
Definition: robin_hash.h:389
tsl::detail_robin_hash::robin_hash::robin_hash
robin_hash(robin_hash &&other) noexcept(std::is_nothrow_move_constructible< Hash >::value &&std::is_nothrow_move_constructible< KeyEqual >::value &&std::is_nothrow_move_constructible< GrowthPolicy >::value &&std::is_nothrow_move_constructible< buckets_container_type >::value)
Definition: robin_hash.h:629
tsl::detail_robin_hash::robin_hash::key_eq
key_equal key_eq() const
Definition: robin_hash.h:1102
tsl::detail_robin_hash::robin_hash::insert_value_impl
void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, truncated_hash_type hash, value_type &value)
Definition: robin_hash.h:1286
tsl::detail_robin_hash::robin_hash::insert
std::pair< iterator, bool > insert(P &&value)
Definition: robin_hash.h:741
tsl::detail_robin_hash::robin_hash::load_factor
float load_factor() const
Definition: robin_hash.h:1063
tsl::detail_robin_hash::robin_hash::insert_value_on_rehash
void insert_value_on_rehash(std::size_t ibucket, distance_type dist_from_ideal_bucket, truncated_hash_type hash, value_type &&value)
Definition: robin_hash.h:1357
tsl::detail_robin_hash::robin_hash< Key, KeySelect, void, std::hash< Key >, std::equal_to< Key >, std::allocator< Key >, false, tsl::rh::power_of_two_growth_policy< 2 > >::const_reference
const value_type & const_reference
Definition: robin_hash.h:386
tsl::detail_robin_hash::robin_hash::deserialize
void deserialize(Deserializer &deserializer, bool hash_compatible)
Definition: robin_hash.h:1117


mp2p_icp
Author(s): Jose-Luis Blanco-Claraco
autogenerated on Wed Jun 26 2024 02:47:09