24 #ifndef TSL_SPARSE_HASH_H 25 #define TSL_SPARSE_HASH_H 39 #include <type_traits> 44 #ifdef __INTEL_COMPILER 45 # include <immintrin.h> 54 # define tsl_sh_assert(expr) assert(expr) 56 # define tsl_sh_assert(expr) (static_cast<void>(0
)) 88 static_assert(
sizeof(
unsigned long long int) ==
sizeof(std::uint64_t),
89 "sizeof(unsigned long long int) must be equal to sizeof(std::uint64_t). " 90 "Open a feature request if you need support for a platform where it isn't the case.");
92 const std::uint64_t m1 = 0x5555555555555555ull;
93 const std::uint64_t m2 = 0x3333333333333333ull;
94 const std::uint64_t m4 = 0x0f0f0f0f0f0f0f0full;
95 const std::uint64_t h01 = 0x0101010101010101ull;
97 x -= (x >> 1ull) & m1;
98 x = (x & m2) + ((x >> 2ull) & m2);
99 x = (x + (x >> 4ull)) & m4;
100 return static_cast<
int>((x * h01) >> (64ull - 8ull));
104 static_assert(
sizeof(
unsigned int) ==
sizeof(std::uint32_t) ||
sizeof(
unsigned int) ==
sizeof(std::uint64_t),
105 "sizeof(unsigned int) must be equal to sizeof(std::uint32_t) or sizeof(std::uint64_t). " 106 "Open a feature request if you need support for a platform where it isn't the case.");
108 if (
sizeof(
unsigned int) ==
sizeof(std::uint32_t)) {
109 const std::uint32_t m1 = 0x55555555;
110 const std::uint32_t m2 = 0x33333333;
111 const std::uint32_t m4 = 0x0f0f0f0f;
112 const std::uint32_t h01 = 0x01010101;
115 x = (x & m2) + ((x >> 2) & m2);
116 x = (x + (x >> 4)) & m4;
117 return static_cast<
int>((x * h01) >> (32 - 8));
125 #if defined(__clang__
) || defined(__GNUC__
) 126 inline int popcountll(
unsigned long long int value) {
127 return __builtin_popcountll(value);
130 inline int popcount(
unsigned int value) {
131 return __builtin_popcount(value);
135 #elif defined(_MSC_VER) 148 static_assert(
sizeof(
unsigned long long int) ==
sizeof(
std::
int64_t),
149 "sizeof(unsigned long long int) must be equal to sizeof(std::int64_t). ");
159 static_assert(
sizeof(
unsigned int) ==
sizeof(
std::
int32_t),
160 "sizeof(unsigned int) must be equal to sizeof(std::int32_t). ");
167 #elif defined(__INTEL_COMPILER) 169 static_assert(
sizeof(
unsigned long long int) ==
sizeof(
__int64),
"");
200 template<
typename T,
typename =
void>
201 struct has_is_transparent: std::false_type {
205 struct has_is_transparent<T,
typename make_void<
typename T::is_transparent>::type>: std::true_type {
209 struct is_power_of_two_policy: std::false_type {
212 template<std::size_t GrowthFactor>
218 return value != 0 && (value & (value - 1)) == 0;
231 for(std::size_t i = 1; i <
sizeof(std::size_t) * CHAR_BIT; i *= 2) {
238 template<
typename T,
typename U>
239 static T numeric_cast(U value,
const char* error_message =
"numeric_cast() failed.") {
240 T ret =
static_cast<T>(value);
241 if(
static_cast<U>(ret) != value) {
242 throw std::runtime_error(error_message);
245 const bool is_same_signedness = (std::is_unsigned<T>::value && std::is_unsigned<U>::value) ||
246 (std::is_signed<T>::value && std::is_signed<U>::value);
247 if(is_same_signedness && (ret < T{}) != (value < U{})) {
248 throw std::runtime_error(error_message);
259 using slz_size_type = std::uint64_t;
260 static_assert(std::numeric_limits<slz_size_type>::max() >= std::numeric_limits<std::size_t>::max(),
261 "slz_size_type must be >= std::size_t");
263 template<
class T,
class Deserializer>
264 static T deserialize_value(Deserializer& deserializer) {
266 #if defined (_MSC_VER) && _MSC_VER < 1910
267 return deserializer.Deserializer::operator()<T>();
269 return deserializer.Deserializer::
template operator()<T>();
297 template<
typename T,
typename Allocator,
tsl::
sh::
sparsity Sparsity>
300 using value_type = T;
301 using size_type = std::uint_least8_t;
302 using allocator_type = Allocator;
303 using iterator = value_type*;
304 using const_iterator =
const value_type*;
316 #if SIZE_MAX
<= UINT32_MAX
317 using bitmap_type = std::uint_least32_t;
318 static const std::size_t BITMAP_NB_BITS = 32;
319 static const std::size_t BUCKET_SHIFT = 5;
321 using bitmap_type = std::uint_least64_t;
322 static const std::size_t BITMAP_NB_BITS = 64;
323 static const std::size_t BUCKET_SHIFT = 6;
326 static const std::size_t BUCKET_MASK = BITMAP_NB_BITS - 1;
328 static_assert(
is_power_of_two(BITMAP_NB_BITS
),
"BITMAP_NB_BITS must be a power of two.");
329 static_assert(std::numeric_limits<bitmap_type>::digits >= BITMAP_NB_BITS,
330 "bitmap_type must be able to hold at least BITMAP_NB_BITS.");
331 static_assert((std::size_t(1) << BUCKET_SHIFT) == BITMAP_NB_BITS,
332 "(1 << BUCKET_SHIFT) must be equal to BITMAP_NB_BITS.");
333 static_assert(std::numeric_limits<size_type>::max() >= BITMAP_NB_BITS,
334 "size_type must be big enough to hold BITMAP_NB_BITS.");
335 static_assert(std::is_unsigned<bitmap_type>::value,
"bitmap_type must be unsigned.");
336 static_assert((std::numeric_limits<bitmap_type>::max() & BUCKET_MASK) == BITMAP_NB_BITS - 1,
"");
340 static const std::size_t DEFAULT_INIT_BUCKETS_SIZE = BITMAP_NB_BITS;
349 static std::size_t sparse_ibucket(std::size_t ibucket) {
350 return ibucket >> BUCKET_SHIFT;
360 static typename sparse_array::size_type index_in_sparse_bucket(std::size_t ibucket) {
361 return static_cast<
typename sparse_array::size_type>(ibucket & sparse_array::BUCKET_MASK);
366 sparse_array()
noexcept: m_values(
nullptr), m_bitmap_vals(0), m_bitmap_deleted_vals(0),
367 m_nb_elements(0), m_capacity(0), m_last_array(
false)
371 explicit sparse_array(
bool last_bucket)
noexcept: m_values(
nullptr), m_bitmap_vals(0), m_bitmap_deleted_vals(0),
372 m_nb_elements(0), m_capacity(0), m_last_array(last_bucket)
376 sparse_array(size_type capacity, Allocator& alloc): m_values(
nullptr), m_bitmap_vals(0), m_bitmap_deleted_vals(0),
377 m_nb_elements(0), m_capacity(capacity), m_last_array(
false)
380 m_values = alloc.allocate(m_capacity);
385 sparse_array(
const sparse_array& other, Allocator& alloc):
386 m_values(
nullptr), m_bitmap_vals(other.m_bitmap_vals),
387 m_bitmap_deleted_vals(other.m_bitmap_deleted_vals),
388 m_nb_elements(0), m_capacity(other.m_capacity),
389 m_last_array(other.m_last_array)
392 if(m_capacity == 0) {
396 m_values = alloc.allocate(m_capacity);
399 for(size_type i = 0; i < other.m_nb_elements; i++) {
400 construct_value(alloc, m_values + i, other.m_values[i]);
410 sparse_array(sparse_array&& other)
noexcept: m_values(other.m_values), m_bitmap_vals(other.m_bitmap_vals),
411 m_bitmap_deleted_vals(other.m_bitmap_deleted_vals),
412 m_nb_elements(other.m_nb_elements), m_capacity(other.m_capacity),
413 m_last_array(other.m_last_array)
415 other.m_values =
nullptr;
416 other.m_bitmap_vals = 0;
417 other.m_bitmap_deleted_vals = 0;
418 other.m_nb_elements = 0;
419 other.m_capacity = 0;
422 sparse_array(sparse_array&& other, Allocator& alloc):
423 m_values(
nullptr), m_bitmap_vals(other.m_bitmap_vals),
424 m_bitmap_deleted_vals(other.m_bitmap_deleted_vals),
425 m_nb_elements(0), m_capacity(other.m_capacity),
426 m_last_array(other.m_last_array)
429 if(m_capacity == 0) {
433 m_values = alloc.allocate(m_capacity);
436 for(size_type i = 0; i < other.m_nb_elements; i++) {
437 construct_value(alloc, m_values + i, std::move(other.m_values[i]));
447 sparse_array& operator=(
const sparse_array& ) =
delete;
448 sparse_array& operator=(sparse_array&& ) =
delete;
450 ~sparse_array()
noexcept {
453 tsl_sh_assert(m_capacity == 0 && m_nb_elements == 0 && m_values ==
nullptr);
456 iterator begin()
noexcept {
return m_values; }
457 iterator end()
noexcept {
return m_values + m_nb_elements; }
458 const_iterator begin()
const noexcept {
return cbegin(); }
459 const_iterator end()
const noexcept {
return cend(); }
460 const_iterator cbegin()
const noexcept {
return m_values; }
461 const_iterator cend()
const noexcept {
return m_values + m_nb_elements; }
463 bool empty()
const noexcept {
464 return m_nb_elements == 0;
467 size_type size()
const noexcept {
468 return m_nb_elements;
471 void clear(allocator_type& alloc)
noexcept {
472 destroy_and_deallocate_values(alloc, m_values, m_nb_elements, m_capacity);
476 m_bitmap_deleted_vals = 0;
481 bool last()
const noexcept {
485 void set_as_last()
noexcept {
489 bool has_value(size_type index)
const noexcept {
491 return (m_bitmap_vals & (bitmap_type(1) << index)) != 0;
494 bool has_deleted_value(size_type index)
const noexcept {
496 return (m_bitmap_deleted_vals & (bitmap_type(1) << index)) != 0;
499 iterator value(size_type index)
noexcept {
501 return m_values + index_to_offset(index);
504 const_iterator value(size_type index)
const noexcept {
506 return m_values + index_to_offset(index);
512 template<
typename... Args>
513 iterator set(allocator_type& alloc, size_type index, Args&&... value_args) {
516 const size_type offset = index_to_offset(index);
517 insert_at_offset(alloc, offset, std::forward<Args>(value_args)...);
519 m_bitmap_vals = (m_bitmap_vals | (bitmap_type(1) << index));
520 m_bitmap_deleted_vals = (m_bitmap_deleted_vals & ~(bitmap_type(1) << index));
527 return m_values + offset;
530 iterator erase(allocator_type& alloc, iterator position) {
531 const size_type offset =
static_cast<size_type>(std::distance(begin(), position));
532 return erase(alloc, position, offset_to_index(offset));
536 iterator erase(allocator_type& alloc, iterator position, size_type index) {
540 const size_type offset =
static_cast<size_type>(std::distance(begin(), position));
541 erase_at_offset(alloc, offset);
543 m_bitmap_vals = (m_bitmap_vals & ~(bitmap_type(1) << index));
544 m_bitmap_deleted_vals = (m_bitmap_deleted_vals | (bitmap_type(1) << index));
551 return m_values + offset;
554 void swap(sparse_array& other) {
557 swap(m_values, other.m_values);
558 swap(m_bitmap_vals, other.m_bitmap_vals);
559 swap(m_bitmap_deleted_vals, other.m_bitmap_deleted_vals);
560 swap(m_nb_elements, other.m_nb_elements);
561 swap(m_capacity, other.m_capacity);
562 swap(m_last_array, other.m_last_array);
565 static iterator mutable_iterator(const_iterator pos) {
566 return const_cast<iterator>(pos);
569 template<
class Serializer>
570 void serialize(Serializer& serializer)
const {
571 const slz_size_type sparse_bucket_size = m_nb_elements;
572 serializer(sparse_bucket_size);
574 const slz_size_type bitmap_vals = m_bitmap_vals;
575 serializer(bitmap_vals);
577 const slz_size_type bitmap_deleted_vals = m_bitmap_deleted_vals;
578 serializer(bitmap_deleted_vals);
580 for(
const value_type& value: *
this) {
585 template<
class Deserializer>
586 static sparse_array deserialize_hash_compatible(Deserializer& deserializer, Allocator& alloc) {
587 const slz_size_type sparse_bucket_size = deserialize_value<slz_size_type>(deserializer);
588 const slz_size_type bitmap_vals = deserialize_value<slz_size_type>(deserializer);
589 const slz_size_type bitmap_deleted_vals = deserialize_value<slz_size_type>(deserializer);
591 if(sparse_bucket_size > BITMAP_NB_BITS) {
592 throw std::runtime_error(
"Deserialized sparse_bucket_size is too big for the platform. Maximum should be BITMAP_NB_BITS.");
597 if(sparse_bucket_size == 0) {
601 sarray.m_bitmap_vals = numeric_cast<bitmap_type>(bitmap_vals,
"Deserialized bitmap_vals is too big.");
602 sarray.m_bitmap_deleted_vals = numeric_cast<bitmap_type>(bitmap_deleted_vals,
"Deserialized bitmap_deleted_vals is too big.");
604 sarray.m_capacity = numeric_cast<size_type>(sparse_bucket_size,
"Deserialized sparse_bucket_size is too big.");
605 sarray.m_values = alloc.allocate(sarray.m_capacity);
608 for(size_type ivalue = 0; ivalue < sarray.m_capacity; ivalue++) {
609 construct_value(alloc, sarray.m_values + ivalue, deserialize_value<value_type>(deserializer));
610 sarray.m_nb_elements++;
624 template<
class Deserializer,
class SparseHash>
625 static void deserialize_values_into_sparse_hash(Deserializer& deserializer, SparseHash& sparse_hash) {
626 const slz_size_type sparse_bucket_size = deserialize_value<slz_size_type>(deserializer);
628 const slz_size_type bitmap_vals = deserialize_value<slz_size_type>(deserializer);
629 static_cast<
void>(bitmap_vals);
631 const slz_size_type bitmap_deleted_vals = deserialize_value<slz_size_type>(deserializer);
632 static_cast<
void>(bitmap_deleted_vals);
635 for(slz_size_type ivalue = 0; ivalue < sparse_bucket_size; ivalue++) {
636 sparse_hash.insert(deserialize_value<value_type>(deserializer));
641 template<
typename... Args>
642 static void construct_value(allocator_type& alloc, value_type* value, Args&&... value_args) {
643 std::allocator_traits<allocator_type>::construct(alloc, value, std::forward<Args>(value_args)...);
646 static void destroy_value(allocator_type& alloc, value_type* value)
noexcept {
647 std::allocator_traits<allocator_type>::destroy(alloc, value);
650 static void destroy_and_deallocate_values(allocator_type& alloc, value_type* values,
651 size_type nb_values, size_type capacity_values)
noexcept 653 for(size_type i = 0; i < nb_values; i++) {
654 destroy_value(alloc, values + i);
657 alloc.deallocate(values, capacity_values);
660 static size_type popcount(bitmap_type val)
noexcept {
661 if(
sizeof(bitmap_type) <=
sizeof(
unsigned int)) {
662 return static_cast<size_type>(
tsl::
detail_popcount::popcount(
static_cast<
unsigned int>(val)));
669 size_type index_to_offset(size_type index)
const noexcept {
671 return popcount(m_bitmap_vals & ((bitmap_type(1) << index) - bitmap_type(1)));
675 size_type offset_to_index(size_type offset)
const noexcept {
678 bitmap_type bitmap_vals = m_bitmap_vals;
680 size_type nb_ones = 0;
682 while(bitmap_vals != 0) {
683 if((bitmap_vals & 0x1) == 1) {
684 if(nb_ones == offset) {
692 bitmap_vals = bitmap_vals >> 1;
698 size_type next_capacity()
const noexcept {
699 return static_cast<size_type>(m_capacity + CAPACITY_GROWTH_STEP);
721 template<
typename... Args,
typename U = value_type,
722 typename std::enable_if<std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
723 void insert_at_offset(allocator_type& alloc, size_type offset, Args&&... value_args) {
724 if(m_nb_elements < m_capacity) {
725 insert_at_offset_no_realloc(alloc, offset, std::forward<Args>(value_args)...);
728 insert_at_offset_realloc(alloc, offset, next_capacity(), std::forward<Args>(value_args)...);
732 template<
typename... Args,
typename U = value_type,
733 typename std::enable_if<!std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
734 void insert_at_offset(allocator_type& alloc, size_type offset, Args&&... value_args) {
735 insert_at_offset_realloc(alloc, offset, m_nb_elements + 1, std::forward<Args>(value_args)...);
738 template<
typename... Args,
typename U = value_type,
739 typename std::enable_if<std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
740 void insert_at_offset_no_realloc(allocator_type& alloc, size_type offset, Args&&... value_args) {
744 for(size_type i = m_nb_elements; i > offset; i--) {
745 construct_value(alloc, m_values + i, std::move(m_values[i - 1]));
746 destroy_value(alloc, m_values + i - 1);
750 construct_value(alloc, m_values + offset, std::forward<Args>(value_args)...);
753 for(size_type i = offset; i < m_nb_elements; i++) {
754 construct_value(alloc, m_values + i, std::move(m_values[i + 1]));
755 destroy_value(alloc, m_values + i + 1);
761 template<
typename... Args,
typename U = value_type,
762 typename std::enable_if<std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
763 void insert_at_offset_realloc(allocator_type& alloc, size_type offset, size_type new_capacity, Args&&... value_args) {
766 value_type* new_values = alloc.allocate(new_capacity);
770 construct_value(alloc, new_values + offset, std::forward<Args>(value_args)...);
773 alloc.deallocate(new_values, new_capacity);
778 for(size_type i = 0; i < offset; i++) {
779 construct_value(alloc, new_values + i, std::move(m_values[i]));
782 for(size_type i = offset; i < m_nb_elements; i++) {
783 construct_value(alloc, new_values + i + 1, std::move(m_values[i]));
786 destroy_and_deallocate_values(alloc, m_values, m_nb_elements, m_capacity);
788 m_values = new_values;
789 m_capacity = new_capacity;
792 template<
typename... Args,
typename U = value_type,
793 typename std::enable_if<!std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
794 void insert_at_offset_realloc(allocator_type& alloc, size_type offset, size_type new_capacity, Args&&... value_args) {
797 value_type* new_values = alloc.allocate(new_capacity);
800 size_type nb_new_values = 0;
802 for(size_type i = 0; i < offset; i++) {
803 construct_value(alloc, new_values + i, m_values[i]);
807 construct_value(alloc, new_values + offset, std::forward<Args>(value_args)...);
810 for(size_type i = offset; i < m_nb_elements; i++) {
811 construct_value(alloc, new_values + i + 1, m_values[i]);
816 destroy_and_deallocate_values(alloc, new_values, nb_new_values, new_capacity);
822 destroy_and_deallocate_values(alloc, m_values, m_nb_elements, m_capacity);
824 m_values = new_values;
825 m_capacity = new_capacity;
840 template<
typename... Args,
typename U = value_type,
841 typename std::enable_if<std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
842 void erase_at_offset(allocator_type& alloc, size_type offset)
noexcept {
845 destroy_value(alloc, m_values + offset);
847 for(size_type i = offset + 1; i < m_nb_elements; i++) {
848 construct_value(alloc, m_values + i - 1, std::move(m_values[i]));
849 destroy_value(alloc, m_values + i);
853 template<
typename... Args,
typename U = value_type,
854 typename std::enable_if<!std::is_nothrow_move_constructible<U>::value>::type* =
nullptr>
855 void erase_at_offset(allocator_type& alloc, size_type offset) {
859 if(offset + 1 == m_nb_elements) {
860 destroy_value(alloc, m_values + offset);
865 const size_type new_capacity = m_nb_elements - 1;
867 value_type* new_values = alloc.allocate(new_capacity);
870 size_type nb_new_values = 0;
872 for(size_type i = 0; i < m_nb_elements; i++) {
874 construct_value(alloc, new_values + nb_new_values, m_values[i]);
880 destroy_and_deallocate_values(alloc, new_values, nb_new_values, new_capacity);
886 destroy_and_deallocate_values(alloc, m_values, m_nb_elements, m_capacity);
888 m_values = new_values;
889 m_capacity = new_capacity;
893 value_type* m_values;
895 bitmap_type m_bitmap_vals;
896 bitmap_type m_bitmap_deleted_vals;
898 size_type m_nb_elements;
899 size_type m_capacity;
927 template<
class ValueType,
937 class sparse_hash:
private Allocator,
private Hash,
private KeyEqual,
private GrowthPolicy {
940 using has_mapped_type =
typename std::integral_constant<
bool, !std::is_same<U,
void>::value>;
944 static_assert(
noexcept(std::declval<GrowthPolicy>().bucket_for_hash(std::size_t(0))),
"GrowthPolicy::bucket_for_hash must be noexcept.");
945 static_assert(
noexcept(std::declval<GrowthPolicy>().clear()),
"GrowthPolicy::clear must be noexcept.");
948 template<
bool IsConst>
951 using key_type =
typename KeySelect::key_type;
952 using value_type = ValueType;
953 using size_type = std::size_t;
954 using difference_type = std::ptrdiff_t;
956 using key_equal = KeyEqual;
957 using allocator_type = Allocator;
958 using reference = value_type&;
959 using const_reference =
const value_type&;
960 using pointer = value_type*;
961 using const_pointer =
const value_type*;
969 using sparse_buckets_allocator =
970 typename std::allocator_traits<allocator_type>::
template rebind_alloc<sparse_array>;
971 using sparse_buckets_container = std::vector<sparse_array, sparse_buckets_allocator>;
981 template<
bool IsConst>
986 using sparse_bucket_iterator =
typename std::conditional<IsConst,
987 typename sparse_buckets_container::const_iterator,
988 typename sparse_buckets_container::iterator>::type;
990 using sparse_array_iterator =
typename std::conditional<IsConst,
991 typename sparse_array::const_iterator,
992 typename sparse_array::iterator>::type;
997 sparse_iterator(sparse_bucket_iterator sparse_bucket_it,
998 sparse_array_iterator sparse_array_it): m_sparse_buckets_it(sparse_bucket_it),
999 m_sparse_array_it(sparse_array_it)
1004 using iterator_category = std::forward_iterator_tag;
1006 using difference_type = std::ptrdiff_t;
1007 using reference = value_type&;
1008 using pointer = value_type*;
1015 m_sparse_array_it(other.m_sparse_array_it)
1020 return KeySelect()(*m_sparse_array_it);
1023 template<
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value && IsConst>::type* =
nullptr>
1025 return U()(*m_sparse_array_it);
1028 template<
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value && !IsConst>::type* =
nullptr>
1030 return U()(*m_sparse_array_it);
1034 return *m_sparse_array_it;
1038 return std::addressof(*m_sparse_array_it);
1043 ++m_sparse_array_it;
1045 if(m_sparse_array_it == m_sparse_buckets_it->end()) {
1047 if(m_sparse_buckets_it->last()) {
1048 ++m_sparse_buckets_it;
1049 m_sparse_array_it =
nullptr;
1053 ++m_sparse_buckets_it;
1054 }
while(m_sparse_buckets_it->empty());
1056 m_sparse_array_it = m_sparse_buckets_it->begin();
1070 return lhs.m_sparse_buckets_it == rhs.m_sparse_buckets_it &&
1071 lhs.m_sparse_array_it == rhs.m_sparse_array_it;
1075 return !(lhs == rhs);
1079 sparse_bucket_iterator m_sparse_buckets_it;
1080 sparse_array_iterator m_sparse_array_it;
1087 const KeyEqual& equal,
1088 const Allocator& alloc,
1089 float max_load_factor): Allocator(alloc),
1092 GrowthPolicy(bucket_count),
1093 m_sparse_buckets(alloc),
1095 m_bucket_count(bucket_count),
1097 m_nb_deleted_buckets(0)
1100 throw std::length_error(
"The map exceeds its maxmimum size.");
1103 if(m_bucket_count > 0) {
1112 const size_type nb_sparse_buckets =
1113 std::max(size_type(1),
1116 m_sparse_buckets.resize(nb_sparse_buckets);
1117 m_first_or_empty_sparse_bucket = m_sparse_buckets.data();
1120 m_sparse_buckets.back().set_as_last();
1124 this->max_load_factor(max_load_factor);
1129 static_assert(std::is_nothrow_move_constructible<value_type>::value ||
1130 std::is_copy_constructible<value_type>::value,
1131 "Key, and T if present, must be nothrow move constructible and/or copy constructible.");
1139 Allocator(std::allocator_traits<Allocator>::select_on_container_copy_construction(other)),
1142 GrowthPolicy(other),
1143 m_sparse_buckets(std::allocator_traits<Allocator>::select_on_container_copy_construction(other)),
1144 m_bucket_count(other.m_bucket_count),
1145 m_nb_elements(other.m_nb_elements),
1146 m_nb_deleted_buckets(other.m_nb_deleted_buckets),
1147 m_load_threshold_rehash(other.m_load_threshold_rehash),
1148 m_load_threshold_clear_deleted(other.m_load_threshold_clear_deleted),
1149 m_max_load_factor(other.m_max_load_factor)
1151 copy_buckets_from(other),
1152 m_first_or_empty_sparse_bucket = m_sparse_buckets.data();
1160 : Allocator(std::move(other)),
1161 Hash(std::move(other)),
1162 KeyEqual(std::move(other)),
1163 GrowthPolicy(std::move(other)),
1164 m_sparse_buckets(std::move(other.m_sparse_buckets)),
1166 m_sparse_buckets.data()),
1167 m_bucket_count(other.m_bucket_count),
1168 m_nb_elements(other.m_nb_elements),
1169 m_nb_deleted_buckets(other.m_nb_deleted_buckets),
1170 m_load_threshold_rehash(other.m_load_threshold_rehash),
1171 m_load_threshold_clear_deleted(other.m_load_threshold_clear_deleted),
1172 m_max_load_factor(other.m_max_load_factor)
1174 other.GrowthPolicy::clear();
1175 other.m_sparse_buckets.clear();
1177 other.m_bucket_count = 0;
1178 other.m_nb_elements = 0;
1179 other.m_nb_deleted_buckets = 0;
1180 other.m_load_threshold_rehash = 0;
1181 other.m_load_threshold_clear_deleted = 0;
1185 if(
this != &other) {
1188 if(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
1189 Allocator::operator=(other);
1192 Hash::operator=(other);
1193 KeyEqual::operator=(other);
1194 GrowthPolicy::operator=(other);
1196 if(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
1197 m_sparse_buckets = sparse_buckets_container(
static_cast<
const Allocator&>(other));
1200 if(m_sparse_buckets.size() != other.m_sparse_buckets.size()) {
1201 m_sparse_buckets = sparse_buckets_container(
static_cast<
const Allocator&>(*
this));
1204 m_sparse_buckets.clear();
1208 copy_buckets_from(other);
1210 m_sparse_buckets.data();
1213 m_bucket_count = other.m_bucket_count;
1214 m_nb_elements = other.m_nb_elements;
1215 m_nb_deleted_buckets = other.m_nb_deleted_buckets;
1216 m_load_threshold_rehash = other.m_load_threshold_rehash;
1217 m_load_threshold_clear_deleted = other.m_load_threshold_clear_deleted;
1218 m_max_load_factor = other.m_max_load_factor;
1227 if(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
1228 static_cast<Allocator&>(*
this) = std::move(
static_cast<Allocator&>(other));
1229 m_sparse_buckets = std::move(other.m_sparse_buckets);
1231 else if(
static_cast<Allocator&>(*
this) !=
static_cast<Allocator&>(other)) {
1232 move_buckets_from(std::move(other));
1235 static_cast<Allocator&>(*
this) = std::move(
static_cast<Allocator&>(other));
1236 m_sparse_buckets = std::move(other.m_sparse_buckets);
1241 m_sparse_buckets.data();
1243 static_cast<Hash&>(*
this) = std::move(
static_cast<Hash&>(other));
1244 static_cast<KeyEqual&>(*
this) = std::move(
static_cast<KeyEqual&>(other));
1245 static_cast<GrowthPolicy&>(*
this) = std::move(
static_cast<GrowthPolicy&>(other));
1246 m_bucket_count = other.m_bucket_count;
1247 m_nb_elements = other.m_nb_elements;
1248 m_nb_deleted_buckets = other.m_nb_deleted_buckets;
1249 m_load_threshold_rehash = other.m_load_threshold_rehash;
1250 m_load_threshold_clear_deleted = other.m_load_threshold_clear_deleted;
1251 m_max_load_factor = other.m_max_load_factor;
1253 other.GrowthPolicy::clear();
1254 other.m_sparse_buckets.clear();
1256 other.m_bucket_count = 0;
1257 other.m_nb_elements = 0;
1258 other.m_nb_deleted_buckets = 0;
1259 other.m_load_threshold_rehash = 0;
1260 other.m_load_threshold_clear_deleted = 0;
1266 return static_cast<
const Allocator&>(*
this);
1274 auto begin = m_sparse_buckets.begin();
1275 while(begin != m_sparse_buckets.end() && begin->empty()) {
1279 return iterator(begin, (begin != m_sparse_buckets.end())?begin->begin():
nullptr);
1287 auto begin = m_sparse_buckets.cbegin();
1288 while(begin != m_sparse_buckets.cend() && begin->empty()) {
1292 return const_iterator(begin, (begin != m_sparse_buckets.cend())?begin->cbegin():
nullptr);
1296 return iterator(m_sparse_buckets.end(),
nullptr);
1299 const_iterator
end()
const noexcept {
1303 const_iterator
cend()
const noexcept {
1304 return const_iterator(m_sparse_buckets.cend(),
nullptr);
1312 return m_nb_elements == 0;
1316 return m_nb_elements;
1320 return std::min(std::allocator_traits<Allocator>::max_size(), m_sparse_buckets.max_size());
1327 for(
auto& bucket: m_sparse_buckets) {
1328 bucket.clear(*
this);
1332 m_nb_deleted_buckets = 0;
1337 template<
typename P>
1338 std::pair<iterator,
bool>
insert(P&& value) {
1339 return insert_impl(KeySelect()(value), std::forward<P>(value));
1342 template<
typename P>
1343 iterator
insert(const_iterator hint, P&& value) {
1344 if(hint !=
cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) {
1348 return insert(std::forward<P>(value)).first;
1351 template<
class InputIt>
1353 if(std::is_base_of<std::forward_iterator_tag,
1354 typename std::iterator_traits<InputIt>::iterator_category>::value)
1356 const auto nb_elements_insert = std::distance(first, last);
1357 const size_type nb_free_buckets = m_load_threshold_rehash -
size();
1360 if(nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) {
1365 for(; first != last; ++first) {
1372 template<
class K,
class M>
1374 auto it = try_emplace(std::forward<K>(key), std::forward<M>(obj));
1376 it.first.value() = std::forward<M>(obj);
1382 template<
class K,
class M>
1384 if(hint !=
cend() && compare_keys(KeySelect()(*hint), key)) {
1386 it.value() = std::forward<M>(obj);
1391 return insert_or_assign(std::forward<K>(key), std::forward<M>(obj)).first;
1395 template<
class... Args>
1396 std::pair<iterator,
bool>
emplace(Args&&... args) {
1397 return insert(value_type(std::forward<Args>(args)...));
1400 template<
class... Args>
1402 return insert(hint, value_type(std::forward<Args>(args)...));
1407 template<
class K,
class... Args>
1409 return insert_impl(key, std::piecewise_construct,
1410 std::forward_as_tuple(std::forward<K>(key)),
1411 std::forward_as_tuple(std::forward<Args>(args)...));
1414 template<
class K,
class... Args>
1416 if(hint !=
cend() && compare_keys(KeySelect()(*hint), key)) {
1420 return try_emplace(std::forward<K>(key), std::forward<Args>(args)...).first;
1429 auto it_sparse_array_next = pos.m_sparse_buckets_it->erase(*
this, pos.m_sparse_array_it);
1431 m_nb_deleted_buckets++;
1433 if(it_sparse_array_next == pos.m_sparse_buckets_it->end()) {
1434 auto it_sparse_buckets_next = pos.m_sparse_buckets_it;
1436 ++it_sparse_buckets_next;
1437 }
while(it_sparse_buckets_next != m_sparse_buckets.end() && it_sparse_buckets_next->empty());
1439 if(it_sparse_buckets_next == m_sparse_buckets.end()) {
1443 return iterator(it_sparse_buckets_next, it_sparse_buckets_next->begin());
1447 return iterator(pos.m_sparse_buckets_it, it_sparse_array_next);
1455 iterator
erase(const_iterator first, const_iterator last) {
1461 const size_type nb_elements_to_erase =
static_cast<size_type>(std::distance(first, last));
1463 for(size_type i = 0; i < nb_elements_to_erase; i++) {
1464 to_delete = erase(to_delete);
1473 return erase(key, hash_key(key));
1477 size_type
erase(
const K& key, std::size_t hash) {
1478 return erase_impl(key, hash);
1486 if(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
1487 swap(
static_cast<Allocator&>(*
this),
static_cast<Allocator&>(other));
1490 tsl_sh_assert(
static_cast<Allocator&>(*
this) ==
static_cast<Allocator&>(other));
1493 swap(
static_cast<Hash&>(*
this),
static_cast<Hash&>(other));
1494 swap(
static_cast<KeyEqual&>(*
this),
static_cast<KeyEqual&>(other));
1495 swap(
static_cast<GrowthPolicy&>(*
this),
static_cast<GrowthPolicy&>(other));
1496 swap(m_sparse_buckets, other.m_sparse_buckets);
1497 swap(m_first_or_empty_sparse_bucket, other.m_first_or_empty_sparse_bucket);
1498 swap(m_bucket_count, other.m_bucket_count);
1499 swap(m_nb_elements, other.m_nb_elements);
1500 swap(m_nb_deleted_buckets, other.m_nb_deleted_buckets);
1501 swap(m_load_threshold_rehash, other.m_load_threshold_rehash);
1502 swap(m_load_threshold_clear_deleted, other.m_load_threshold_clear_deleted);
1503 swap(m_max_load_factor, other.m_max_load_factor);
1510 template<
class K,
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value>::type* =
nullptr>
1512 return at(key, hash_key(key));
1515 template<
class K,
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value>::type* =
nullptr>
1517 return const_cast<
typename U::value_type&>(
static_cast<
const sparse_hash*>(
this)->at(key, hash));
1521 template<
class K,
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value>::type* =
nullptr>
1523 return at(key, hash_key(key));
1526 template<
class K,
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value>::type* =
nullptr>
1528 auto it = find(key, hash);
1533 throw std::out_of_range(
"Couldn't find key.");
1537 template<
class K,
class U = ValueSelect,
typename std::enable_if<has_mapped_type<U>::value>::type* =
nullptr>
1539 return try_emplace(std::forward<K>(key)).first.value();
1545 return count(key, hash_key(key));
1549 size_type
count(
const K& key, std::size_t hash)
const {
1550 if(find(key, hash) !=
cend()) {
1561 return find_impl(key, hash_key(key));
1565 iterator
find(
const K& key, std::size_t hash) {
1566 return find_impl(key, hash);
1571 const_iterator
find(
const K& key)
const {
1572 return find_impl(key, hash_key(key));
1576 const_iterator
find(
const K& key, std::size_t hash)
const {
1577 return find_impl(key, hash);
1583 return equal_range(key, hash_key(key));
1587 std::pair<iterator, iterator>
equal_range(
const K& key, std::size_t hash) {
1588 iterator it = find(key, hash);
1589 return std::make_pair(it, (it == end())?it:std::next(it));
1594 std::pair<const_iterator, const_iterator>
equal_range(
const K& key)
const {
1595 return equal_range(key, hash_key(key));
1599 std::pair<const_iterator, const_iterator>
equal_range(
const K& key, std::size_t hash)
const {
1600 const_iterator it = find(key, hash);
1601 return std::make_pair(it, (it ==
cend())?it:std::next(it));
1608 return m_bucket_count;
1612 return m_sparse_buckets.max_size();
1627 return m_max_load_factor;
1631 m_max_load_factor = std::max(0.1f, std::min(ml, 0.8f));
1632 m_load_threshold_rehash = size_type(
float(
bucket_count())*m_max_load_factor);
1634 const float max_load_factor_with_deleted_buckets = m_max_load_factor + 0.5f*(1.0f - m_max_load_factor);
1635 tsl_sh_assert(max_load_factor_with_deleted_buckets > 0.0f && max_load_factor_with_deleted_buckets <= 1.0f);
1636 m_load_threshold_clear_deleted = size_type(
float(
bucket_count())*max_load_factor_with_deleted_buckets);
1640 count = std::max(count, size_type(std::ceil(
float(
size())/max_load_factor())));
1645 rehash(size_type(std::ceil(
float(count)/max_load_factor()))
);
1652 return static_cast<
const Hash&>(*
this);
1656 return static_cast<
const KeyEqual&>(*
this);
1664 auto it_sparse_buckets = m_sparse_buckets.begin() +
1665 std::distance(m_sparse_buckets.cbegin(), pos.m_sparse_buckets_it);
1667 return iterator(it_sparse_buckets, sparse_array::mutable_iterator(pos.m_sparse_array_it));
1670 template<
class Serializer>
1672 serialize_impl(serializer);
1675 template<
class Deserializer>
1677 deserialize_impl(deserializer, hash_compatible);
1682 std::size_t hash_key(
const K& key)
const {
1683 return Hash::operator()(key);
1686 template<
class K1,
class K2>
1687 bool compare_keys(
const K1& key1,
const K2& key2)
const {
1688 return KeyEqual::operator()(key1, key2);
1691 size_type bucket_for_hash(std::size_t hash)
const {
1692 const std::size_t bucket = GrowthPolicy::bucket_for_hash(hash);
1693 tsl_sh_assert(sparse_array::sparse_ibucket(bucket) < m_sparse_buckets.size() ||
1694 (bucket == 0 && m_sparse_buckets.empty()));
1699 template<
class U = GrowthPolicy,
typename std::enable_if<is_power_of_two_policy<U>::value>::type* =
nullptr>
1700 size_type next_bucket(size_type ibucket, size_type iprobe)
const {
1703 return (ibucket + 1) &
this->m_mask;
1707 return (ibucket + iprobe) &
this->m_mask;
1711 template<
class U = GrowthPolicy,
typename std::enable_if<!is_power_of_two_policy<U>::value>::type* =
nullptr>
1712 size_type next_bucket(size_type ibucket, size_type iprobe)
const {
1727 void copy_buckets_from(
const sparse_hash& other) {
1728 m_sparse_buckets.reserve(other.m_sparse_buckets.size());
1731 for(
const auto& bucket: other.m_sparse_buckets) {
1732 m_sparse_buckets.emplace_back(bucket,
static_cast<Allocator&>(*
this));
1740 tsl_sh_assert(m_sparse_buckets.empty() || m_sparse_buckets.back().last());
1744 m_sparse_buckets.reserve(other.m_sparse_buckets.size());
1747 for(
auto&& bucket: other.m_sparse_buckets) {
1748 m_sparse_buckets.emplace_back(std::move(bucket),
static_cast<Allocator&>(*
this));
1756 tsl_sh_assert(m_sparse_buckets.empty() || m_sparse_buckets.back().last());
1760 template<
class K,
class... Args>
1761 std::pair<iterator,
bool> insert_impl(
const K& key, Args&&... value_type_args) {
1762 if(
size() >= m_load_threshold_rehash) {
1763 rehash_impl(GrowthPolicy::next_bucket_count());
1765 else if(
size() + m_nb_deleted_buckets >= m_load_threshold_clear_deleted) {
1766 clear_deleted_buckets();
1777 bool found_first_deleted_bucket =
false;
1778 std::size_t sparse_ibucket_first_deleted = 0;
1779 typename sparse_array::size_type index_in_sparse_bucket_first_deleted = 0;
1783 const std::size_t hash = hash_key(key);
1784 std::size_t ibucket = bucket_for_hash(hash);
1786 std::size_t probe = 0;
1788 std::size_t sparse_ibucket = sparse_array::sparse_ibucket(ibucket);
1789 auto index_in_sparse_bucket = sparse_array::index_in_sparse_bucket(ibucket);
1791 if(m_sparse_buckets[sparse_ibucket].has_value(index_in_sparse_bucket)) {
1792 auto value_it = m_sparse_buckets[sparse_ibucket].value(index_in_sparse_bucket);
1793 if(compare_keys(key, KeySelect()(*value_it))) {
1794 return std::make_pair(iterator(m_sparse_buckets.begin() + sparse_ibucket, value_it),
false);
1797 else if(m_sparse_buckets[sparse_ibucket].has_deleted_value(index_in_sparse_bucket) &&
1798 probe < m_bucket_count)
1800 if(!found_first_deleted_bucket) {
1801 found_first_deleted_bucket =
true;
1802 sparse_ibucket_first_deleted = sparse_ibucket;
1803 index_in_sparse_bucket_first_deleted = index_in_sparse_bucket;
1806 else if(found_first_deleted_bucket) {
1807 auto it = insert_in_bucket(sparse_ibucket_first_deleted, index_in_sparse_bucket_first_deleted,
1808 std::forward<Args>(value_type_args)...);
1809 m_nb_deleted_buckets--;
1814 return insert_in_bucket(sparse_ibucket, index_in_sparse_bucket,
1815 std::forward<Args>(value_type_args)...);
1819 ibucket = next_bucket(ibucket, probe);
1823 template<
class... Args>
1824 std::pair<iterator,
bool> insert_in_bucket(std::size_t sparse_ibucket,
1825 typename sparse_array::size_type index_in_sparse_bucket,
1826 Args&&... value_type_args)
1828 auto value_it = m_sparse_buckets[sparse_ibucket].set(*
this, index_in_sparse_bucket,
1829 std::forward<Args>(value_type_args)...);
1832 return std::make_pair(iterator(m_sparse_buckets.begin() + sparse_ibucket, value_it),
true);
1840 size_type erase_impl(
const K& key, std::size_t hash) {
1841 std::size_t ibucket = bucket_for_hash(hash);
1843 std::size_t probe = 0;
1845 const std::size_t sparse_ibucket = sparse_array::sparse_ibucket(ibucket);
1846 const auto index_in_sparse_bucket = sparse_array::index_in_sparse_bucket(ibucket);
1848 if((m_first_or_empty_sparse_bucket + sparse_ibucket)->has_value(index_in_sparse_bucket)) {
1849 auto value_it = (m_first_or_empty_sparse_bucket + sparse_ibucket)->value(index_in_sparse_bucket);
1850 if(compare_keys(key, KeySelect()(*value_it))) {
1851 (m_first_or_empty_sparse_bucket + sparse_ibucket)->erase(*
this, value_it, index_in_sparse_bucket);
1853 m_nb_deleted_buckets++;
1858 else if(!(m_first_or_empty_sparse_bucket + sparse_ibucket)->has_deleted_value(index_in_sparse_bucket) || probe >= m_bucket_count) {
1863 ibucket = next_bucket(ibucket, probe);
1870 iterator find_impl(
const K& key, std::size_t hash) {
1875 const_iterator find_impl(
const K& key, std::size_t hash)
const {
1876 std::size_t ibucket = bucket_for_hash(hash);
1878 std::size_t probe = 0;
1880 const std::size_t sparse_ibucket = sparse_array::sparse_ibucket(ibucket);
1881 const auto index_in_sparse_bucket = sparse_array::index_in_sparse_bucket(ibucket);
1883 if((m_first_or_empty_sparse_bucket + sparse_ibucket)->has_value(index_in_sparse_bucket)) {
1884 auto value_it = (m_first_or_empty_sparse_bucket + sparse_ibucket)->value(index_in_sparse_bucket);
1885 if(compare_keys(key, KeySelect()(*value_it))) {
1886 return const_iterator(m_sparse_buckets.cbegin() + sparse_ibucket, value_it);
1889 else if(!(m_first_or_empty_sparse_bucket + sparse_ibucket)->has_deleted_value(index_in_sparse_bucket) || probe >= m_bucket_count) {
1894 ibucket = next_bucket(ibucket, probe);
1898 void clear_deleted_buckets() {
1900 rehash_impl(m_bucket_count);
1906 void rehash_impl(size_type count) {
1907 sparse_hash new_table(count,
static_cast<Hash&>(*
this),
static_cast<KeyEqual&>(*
this),
1908 static_cast<Allocator&>(*
this), m_max_load_factor);
1910 for(
auto& bucket: m_sparse_buckets) {
1911 for(
auto& val: bucket) {
1912 new_table.insert_on_rehash(std::move(val));
1916 bucket.clear(*
this);
1919 new_table.swap(*
this);
1929 void rehash_impl(size_type count) {
1930 sparse_hash new_table(count,
static_cast<Hash&>(*
this),
static_cast<KeyEqual&>(*
this),
1931 static_cast<Allocator&>(*
this), m_max_load_factor);
1933 for(
const auto& bucket: m_sparse_buckets) {
1934 for(
const auto& val: bucket) {
1935 new_table.insert_on_rehash(val);
1939 new_table.swap(*
this);
1943 template<
typename K>
1944 void insert_on_rehash(K&& key_value) {
1945 const key_type& key = KeySelect()(key_value);
1947 const std::size_t hash = hash_key(key);
1948 std::size_t ibucket = bucket_for_hash(hash);
1950 std::size_t probe = 0;
1952 std::size_t sparse_ibucket = sparse_array::sparse_ibucket(ibucket);
1953 auto index_in_sparse_bucket = sparse_array::index_in_sparse_bucket(ibucket);
1955 if(!(m_first_or_empty_sparse_bucket + sparse_ibucket)->has_value(index_in_sparse_bucket)) {
1956 (m_first_or_empty_sparse_bucket + sparse_ibucket)->set(*
this, index_in_sparse_bucket,
1957 std::forward<K>(key_value));
1964 KeySelect()(*(m_first_or_empty_sparse_bucket + sparse_ibucket)->value(index_in_sparse_bucket))));
1968 ibucket = next_bucket(ibucket, probe);
1972 template<
class Serializer>
1973 void serialize_impl(Serializer& serializer)
const {
1975 serializer(version);
1977 const slz_size_type bucket_count = m_bucket_count;
1978 serializer(bucket_count);
1980 const slz_size_type nb_sparse_buckets = m_sparse_buckets.size();
1981 serializer(nb_sparse_buckets);
1983 const slz_size_type nb_elements = m_nb_elements;
1984 serializer(nb_elements);
1986 const slz_size_type nb_deleted_buckets = m_nb_deleted_buckets;
1987 serializer(nb_deleted_buckets);
1989 const float max_load_factor = m_max_load_factor;
1990 serializer(max_load_factor);
1993 for(
const auto& bucket: m_sparse_buckets) {
1994 bucket.serialize(serializer);
1998 template<
class Deserializer>
1999 void deserialize_impl(Deserializer& deserializer,
bool hash_compatible) {
2000 tsl_sh_assert(m_bucket_count == 0 && m_sparse_buckets.empty());
2002 const slz_size_type version = deserialize_value<slz_size_type>(deserializer);
2006 throw std::runtime_error(
"Can't deserialize the sparse_map/set. The protocol version header is invalid.");
2009 const slz_size_type bucket_count_ds = deserialize_value<slz_size_type>(deserializer);
2010 const slz_size_type nb_sparse_buckets = deserialize_value<slz_size_type>(deserializer);
2011 const slz_size_type nb_elements = deserialize_value<slz_size_type>(deserializer);
2012 const slz_size_type nb_deleted_buckets = deserialize_value<slz_size_type>(deserializer);
2013 const float max_load_factor = deserialize_value<
float>(deserializer);
2016 this->max_load_factor(max_load_factor);
2018 if(bucket_count_ds == 0) {
2024 if(!hash_compatible) {
2025 reserve(numeric_cast<size_type>(nb_elements,
"Deserialized nb_elements is too big.")
);
2026 for(slz_size_type ibucket = 0; ibucket < nb_sparse_buckets; ibucket++) {
2027 sparse_array::deserialize_values_into_sparse_hash(deserializer, *
this);
2031 m_bucket_count = numeric_cast<size_type>(bucket_count_ds,
"Deserialized bucket_count is too big.");
2033 GrowthPolicy::operator=(GrowthPolicy(m_bucket_count));
2035 if(m_bucket_count != bucket_count_ds) {
2036 throw std::runtime_error(
"The GrowthPolicy is not the same even though hash_compatible is true.");
2040 throw std::runtime_error(
"Deserialized nb_sparse_buckets is invalid.");
2044 m_nb_elements = numeric_cast<size_type>(nb_elements,
"Deserialized nb_elements is too big.");
2045 m_nb_deleted_buckets = numeric_cast<size_type>(nb_deleted_buckets,
"Deserialized nb_deleted_buckets is too big.");
2048 m_sparse_buckets.reserve(numeric_cast<size_type>(nb_sparse_buckets,
"Deserialized nb_sparse_buckets is too big."));
2050 for(slz_size_type ibucket = 0; ibucket < nb_sparse_buckets; ibucket++) {
2051 m_sparse_buckets.emplace_back(sparse_array::deserialize_hash_compatible(deserializer,
static_cast<Allocator&>(*
this)));
2054 m_sparse_buckets.back().set_as_last();
2055 m_first_or_empty_sparse_bucket = m_sparse_buckets.data();
2059 throw std::runtime_error(
"Invalid max_load_factor. Check that the serializer and deserializer supports " 2060 "floats correctly as they can be converted implicitely to ints.");
2078 static sparse_array empty_sparse_bucket(
true);
2079 return &empty_sparse_bucket;
2083 sparse_buckets_container m_sparse_buckets;
2092 sparse_array* m_first_or_empty_sparse_bucket;
2094 size_type m_bucket_count;
2095 size_type m_nb_elements;
2096 size_type m_nb_deleted_buckets;
2101 size_type m_load_threshold_rehash;
2106 size_type m_load_threshold_clear_deleted;
2107 float m_max_load_factor;
const_iterator find(const K &key, std::size_t hash) const
Definition: sparse_hash.h:1576
~sparse_hash()
Definition: sparse_hash.h:1134
void deserialize(Deserializer &deserializer, bool hash_compatible)
Definition: sparse_hash.h:1676
std::pair< iterator, iterator > equal_range(const K &key)
Definition: sparse_hash.h:1582
sparse_iterator operator++(int)
Definition: sparse_hash.h:1062
key_equal key_eq() const
Definition: sparse_hash.h:1655
iterator erase(const_iterator pos)
Definition: sparse_hash.h:1451
std::pair< iterator, bool > insert(P &&value)
Definition: sparse_hash.h:1338
sparse_iterator() noexcept
Definition: sparse_hash.h:1011
float max_load_factor() const
Definition: sparse_hash.h:1626
iterator find(const K &key)
Definition: sparse_hash.h:1560
sparse_hash(sparse_hash &&other) noexcept(std::is_nothrow_move_constructible< Allocator >::value &&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< sparse_buckets_container >::value)
Definition: sparse_hash.h:1155
const_iterator find(const K &key) const
Definition: sparse_hash.h:1571
const U::value_type & at(const K &key, std::size_t hash) const
Definition: sparse_hash.h:1527
Definition: sparse_growth_policy.h:39
void rehash(size_type count)
Definition: sparse_hash.h:1639
iterator end() noexcept
Definition: sparse_hash.h:1295
static const size_type DEFAULT_INIT_BUCKETS_SIZE
Definition: sparse_hash.h:2066
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t hash) const
Definition: sparse_hash.h:1599
std::pair< iterator, bool > emplace(Args &&... args)
Definition: sparse_hash.h:1396
U::value_type & value()
Definition: sparse_hash.h:1029
iterator mutable_iterator(const_iterator pos)
Definition: sparse_hash.h:1663
std::size_t round_up_to_power_of_two(std::size_t value)
Definition: sparse_hash.h:221
sparse_array * static_empty_sparse_bucket_ptr()
Definition: sparse_hash.h:2077
pointer operator->() const
Definition: sparse_hash.h:1037
probing
Definition: sparse_hash.h:63
sparse_iterator(const sparse_iterator< false > &other) noexcept
Definition: sparse_hash.h:1014
U::value_type & at(const K &key)
Definition: sparse_hash.h:1511
size_type bucket_count() const
Definition: sparse_hash.h:1607
sparse_hash(size_type bucket_count, const Hash &hash, const KeyEqual &equal, const Allocator &alloc, float max_load_factor)
Definition: sparse_hash.h:1085
iterator try_emplace(const_iterator hint, K &&key, Args &&... args)
Definition: sparse_hash.h:1415
iterator find(const K &key, std::size_t hash)
Definition: sparse_hash.h:1565
bool empty() const noexcept
Definition: sparse_hash.h:1311
iterator insert(const_iterator hint, P &&value)
Definition: sparse_hash.h:1343
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition: sparse_hash.h:1594
sparse_iterator & operator++()
Definition: sparse_hash.h:1041
size_type count(const K &key) const
Definition: sparse_hash.h:1544
sparse_hash & operator=(sparse_hash &&other)
Definition: sparse_hash.h:1224
sparse_hash & operator=(const sparse_hash &other)
Definition: sparse_hash.h:1184
float load_factor() const
Definition: sparse_hash.h:1618
reference operator*() const
Definition: sparse_hash.h:1033
sparsity
Definition: sparse_hash.h:73
static const slz_size_type SERIALIZATION_PROTOCOL_VERSION
Definition: sparse_hash.h:2072
iterator begin() noexcept
Definition: sparse_hash.h:1273
exception_safety
Definition: sparse_hash.h:68
size_type size() const noexcept
Definition: sparse_hash.h:1315
friend class sparse_hash
Definition: sparse_hash.h:983
const sparse_hash::key_type & key() const
Definition: sparse_hash.h:1019
const_iterator cend() const noexcept
Definition: sparse_hash.h:1303
U::value_type & operator[](K &&key)
Definition: sparse_hash.h:1538
U::value_type & at(const K &key, std::size_t hash)
Definition: sparse_hash.h:1516
void max_load_factor(float ml)
Definition: sparse_hash.h:1630
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition: sparse_hash.h:1401
#define tsl_sh_assert(expr)
Definition: sparse_hash.h:56
friend bool operator!=(const sparse_iterator &lhs, const sparse_iterator &rhs)
Definition: sparse_hash.h:1074
allocator_type get_allocator() const
Definition: sparse_hash.h:1265
Definition: sparse_growth_policy.h:40
friend bool operator==(const sparse_iterator &lhs, const sparse_iterator &rhs)
Definition: sparse_hash.h:1069
static constexpr float DEFAULT_MAX_LOAD_FACTOR
Definition: sparse_hash.h:2067
iterator insert_or_assign(const_iterator hint, K &&key, M &&obj)
Definition: sparse_hash.h:1383
size_type erase(const K &key)
Definition: sparse_hash.h:1472
size_type max_size() const noexcept
Definition: sparse_hash.h:1319
size_type erase(const K &key, std::size_t hash)
Definition: sparse_hash.h:1477
const_iterator begin() const noexcept
Definition: sparse_hash.h:1282
iterator erase(const_iterator first, const_iterator last)
Definition: sparse_hash.h:1455
std::pair< iterator, bool > insert_or_assign(K &&key, M &&obj)
Definition: sparse_hash.h:1373
void clear() noexcept
Definition: sparse_hash.h:1326
void reserve(size_type count)
Definition: sparse_hash.h:1644
const U::value_type & at(const K &key) const
Definition: sparse_hash.h:1522
constexpr bool is_power_of_two(std::size_t value)
Definition: sparse_hash.h:217
int fallback_popcountll(unsigned long long int x)
Definition: sparse_hash.h:87
const_iterator cbegin() const noexcept
Definition: sparse_hash.h:1286
const U::value_type & value() const
Definition: sparse_hash.h:1024
int fallback_popcount(unsigned int x)
Definition: sparse_hash.h:103
size_type count(const K &key, std::size_t hash) const
Definition: sparse_hash.h:1549
const_iterator end() const noexcept
Definition: sparse_hash.h:1299
Definition: sparse_hash.h:193
size_type max_bucket_count() const
Definition: sparse_hash.h:1611
void insert(InputIt first, InputIt last)
Definition: sparse_hash.h:1352
iterator erase(iterator pos)
Definition: sparse_hash.h:1427
sparse_hash(const sparse_hash &other)
Definition: sparse_hash.h:1138
int popcount(unsigned int x)
Definition: sparse_hash.h:183
void serialize(Serializer &serializer) const
Definition: sparse_hash.h:1671
void swap(sparse_hash &other)
Definition: sparse_hash.h:1483
hasher hash_function() const
Definition: sparse_hash.h:1651
Definition: sparse_growth_policy.h:49
std::pair< iterator, iterator > equal_range(const K &key, std::size_t hash)
Definition: sparse_hash.h:1587
Definition: sparse_hash.h:937
std::pair< iterator, bool > try_emplace(K &&key, Args &&... args)
Definition: sparse_hash.h:1408