@@ -66,12 +66,6 @@ template <std::size_t GrowthFactor>
66
66
struct is_power_of_two_policy <tsl::rh::power_of_two_growth_policy<GrowthFactor>>
67
67
: std::true_type {};
68
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
69
template <typename T, typename U>
76
70
static T numeric_cast (U value,
77
71
const char * error_message = " numeric_cast() failed." ) {
@@ -87,6 +81,8 @@ static T numeric_cast(U value,
87
81
TSL_RH_THROW_OR_TERMINATE (std::runtime_error, error_message);
88
82
}
89
83
84
+ TSL_RH_UNUSED (error_message);
85
+
90
86
return ret;
91
87
}
92
88
@@ -252,22 +248,14 @@ class bucket_entry : public bucket_entry_hash<StoreHash> {
252
248
253
249
value_type& value () noexcept {
254
250
tsl_rh_assert (!empty ());
255
- #if defined(__cplusplus) && __cplusplus >= 201703L
256
251
return *std::launder (
257
252
reinterpret_cast <value_type*>(std::addressof (m_value)));
258
- #else
259
- return *reinterpret_cast <value_type*>(std::addressof (m_value));
260
- #endif
261
253
}
262
254
263
255
const value_type& value () const noexcept {
264
256
tsl_rh_assert (!empty ());
265
- #if defined(__cplusplus) && __cplusplus >= 201703L
266
257
return *std::launder (
267
258
reinterpret_cast <const value_type*>(std::addressof (m_value)));
268
- #else
269
- return *reinterpret_cast <const value_type*>(std::addressof (m_value));
270
- #endif
271
259
}
272
260
273
261
distance_type dist_from_ideal_bucket () const noexcept {
@@ -597,7 +585,6 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
597
585
using const_iterator = robin_const_iterator;
598
586
599
587
public:
600
- #if defined(__cplusplus) && __cplusplus >= 201402L
601
588
robin_hash (size_type bucket_count, const Hash& hash, const KeyEqual& equal,
602
589
const Allocator& alloc,
603
590
float min_load_factor = DEFAULT_MIN_LOAD_FACTOR,
@@ -625,47 +612,6 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
625
612
this ->min_load_factor (min_load_factor);
626
613
this ->max_load_factor (max_load_factor);
627
614
}
628
- #else
629
- /* *
630
- * C++11 doesn't support the creation of a std::vector with a custom allocator
631
- * and 'count' default-inserted elements. The needed contructor `explicit
632
- * vector(size_type count, const Allocator& alloc = Allocator());` is only
633
- * available in C++14 and later. We thus must resize after using the
634
- * `vector(const Allocator& alloc)` constructor.
635
- *
636
- * We can't use `vector(size_type count, const T& value, const Allocator&
637
- * alloc)` as it requires the value T to be copyable.
638
- */
639
- robin_hash (size_type bucket_count, const Hash& hash, const KeyEqual& equal,
640
- const Allocator& alloc,
641
- float min_load_factor = DEFAULT_MIN_LOAD_FACTOR,
642
- float max_load_factor = DEFAULT_MAX_LOAD_FACTOR)
643
- : Hash(hash),
644
- KeyEqual(equal),
645
- GrowthPolicy(bucket_count),
646
- m_buckets_data(alloc),
647
- m_buckets(static_empty_bucket_ptr()),
648
- m_bucket_count(bucket_count),
649
- m_nb_elements(0 ),
650
- m_grow_on_next_insert(false ),
651
- m_try_shrink_on_next_insert(false ) {
652
- if (bucket_count > max_bucket_count ()) {
653
- TSL_RH_THROW_OR_TERMINATE (std::length_error,
654
- " The map exceeds its maximum bucket count." );
655
- }
656
-
657
- if (m_bucket_count > 0 ) {
658
- m_buckets_data.resize (m_bucket_count);
659
- m_buckets = m_buckets_data.data ();
660
-
661
- tsl_rh_assert (!m_buckets_data.empty ());
662
- m_buckets_data.back ().set_as_last_bucket ();
663
- }
664
-
665
- this ->min_load_factor (min_load_factor);
666
- this ->max_load_factor (max_load_factor);
667
- }
668
- #endif
669
615
670
616
robin_hash (const robin_hash& other)
671
617
: Hash(other),
@@ -876,6 +822,10 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
876
822
return try_emplace (std::forward<K>(key), std::forward<Args>(args)...).first ;
877
823
}
878
824
825
+ void erase_fast (iterator pos) {
826
+ erase_from_bucket (pos);
827
+ }
828
+
879
829
/* *
880
830
* Here to avoid `template<class K> size_type erase(const K& key)` being used
881
831
* when we use an `iterator` instead of a `const_iterator`.
@@ -892,8 +842,6 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
892
842
++pos;
893
843
}
894
844
895
- m_try_shrink_on_next_insert = true ;
896
-
897
845
return pos;
898
846
}
899
847
@@ -972,8 +920,6 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
972
920
auto it = find (key, hash);
973
921
if (it != end ()) {
974
922
erase_from_bucket (it);
975
- m_try_shrink_on_next_insert = true ;
976
-
977
923
return 1 ;
978
924
} else {
979
925
return 0 ;
@@ -1129,13 +1075,13 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
1129
1075
float max_load_factor () const { return m_max_load_factor; }
1130
1076
1131
1077
void min_load_factor (float ml) {
1132
- m_min_load_factor = clamp (ml, float (MINIMUM_MIN_LOAD_FACTOR),
1133
- float (MAXIMUM_MIN_LOAD_FACTOR));
1078
+ m_min_load_factor = std:: clamp (ml, float (MINIMUM_MIN_LOAD_FACTOR),
1079
+ float (MAXIMUM_MIN_LOAD_FACTOR));
1134
1080
}
1135
1081
1136
1082
void max_load_factor (float ml) {
1137
- m_max_load_factor = clamp (ml, float (MINIMUM_MAX_LOAD_FACTOR),
1138
- float (MAXIMUM_MAX_LOAD_FACTOR));
1083
+ m_max_load_factor = std:: clamp (ml, float (MINIMUM_MAX_LOAD_FACTOR),
1084
+ float (MAXIMUM_MAX_LOAD_FACTOR));
1139
1085
m_load_threshold = size_type (float (bucket_count ()) * m_max_load_factor);
1140
1086
tsl_rh_assert (bucket_count () == 0 || m_load_threshold < bucket_count ());
1141
1087
}
@@ -1267,6 +1213,7 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
1267
1213
previous_ibucket = ibucket;
1268
1214
ibucket = next_bucket (ibucket);
1269
1215
}
1216
+ m_try_shrink_on_next_insert = true ;
1270
1217
}
1271
1218
1272
1219
template <class K , class ... Args>
@@ -1579,6 +1526,9 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
1579
1526
} else {
1580
1527
m_bucket_count = numeric_cast<size_type>(
1581
1528
bucket_count_ds, " Deserialized bucket_count is too big." );
1529
+ // Recompute m_load_threshold, during max_load_factor() the bucket count
1530
+ // was still 0 which would trigger rehash on first insert
1531
+ m_load_threshold = size_type (float (bucket_count ()) * m_max_load_factor);
1582
1532
1583
1533
GrowthPolicy::operator =(GrowthPolicy (m_bucket_count));
1584
1534
// GrowthPolicy should not modify the bucket count we got from
0 commit comments