@@ -860,7 +860,7 @@ namespace hud
860860 : allocator_ {allocator}
861861 , max_slot_count_ {compute_max_count (other.max_count () + extra_max_count)}
862862 , count_ {other.count ()}
863- , free_slot_before_grow_(other.free_slot_before_grow_ )
863+ , free_slot_before_grow_(max_slot_before_grow(max_slot_count_) - count_ )
864864 {
865865 // Nothing to allocate, stop here
866866 if (max_slot_count_ == 0 )
@@ -998,7 +998,7 @@ namespace hud
998998 : allocator_ {allocator}
999999 , max_slot_count_ {compute_max_count (other.max_count () + extra_max_count)}
10001000 , count_ {other.count ()}
1001- , free_slot_before_grow_(other.free_slot_before_grow_ )
1001+ , free_slot_before_grow_(max_slot_before_grow(max_slot_count_) - count_ )
10021002 {
10031003 // Nothing to allocate, stop here
10041004 if (max_slot_count_ == 0 )
@@ -1071,47 +1071,34 @@ namespace hud
10711071 constexpr hashset_impl &operator =(const hashset_impl &other) noexcept
10721072 requires (hud::is_copy_constructible_v<slot_type>)
10731073 {
1074- // If `this` allocation is not big enough, clear all, then deallocate, allocate new memory and add all element
1075- // If `this` allocation is big enough, clear all, copy controls, add all elements
1076- if (max_slot_count_ < other. max_slot_count_ || max_slot_count_ == 0 )
1077- {
1078- destroy_all_slots ();
1079- free_control_and_slot (control_ptr_, slot_ptr_, max_slot_count_) ;
1074+ // Destroy all slots
1075+ destroy_all_slots ();
1076+
1077+ // We don't keep the max count of the copied array
1078+ // The requested memory is the number of element in the copied array, not the max slot count.
1079+ const usize max_count_requested = other. count_ ;
10801080
1081- // Copy controls
1081+ // If we have enough allocated memory
1082+ if (max_count_requested <= max_slot_count_)
1083+ {
1084+ // Reset the control to empty if we have allocated memory ( Do nothing if we have nothing because control_ptr_ points to static INIT_GROUP)
1085+ if (max_slot_count_ > 0 )
1086+ {
1087+ hud::memory::set_memory (control_ptr_, control_size_for_max_count (max_slot_count_), empty_byte);
1088+ control_ptr_[max_slot_count_] = sentinel_byte;
1089+ }
1090+ // Copy the allocator if copy_when_container_copy_assigned is true
10821091 if constexpr (hud::allocator_traits<allocator_t >::copy_when_container_copy_assigned::value)
10831092 {
10841093 allocator_ = other.allocator_ ;
10851094 }
1086- max_slot_count_ = other. max_slot_count_ ;
1095+ // Copy the number of element
10871096 count_ = other.count_ ;
1088- free_slot_before_grow_ = other.free_slot_before_grow_ ;
1089-
1090- // Nothing to allocate, stop here
1091- if (other.max_slot_count_ == 0 )
1092- return *this ;
1097+ // Compute the free slot count before growing
1098+ free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
10931099
1094- // Allocate the buffer that will contain controls and aligned slots
1095- // In a constant-evaluated context, bit_cast cannot be used with pointers
1096- // To satisfy the compiler, allocate controls and slots in two separate allocations
1097- usize control_size {allocate_control_and_slot (other.max_slot_count_ )};
1098-
1099- // If constant evaluated context or when slot_type is not bitwise copy constructible
1100- // loop through all slot and construct them regardless of the trivially constructible ( Maybe only for control_ptr_ ) like like grow_capacity
1101- // In a non constant evaluated context
1102- // If type is trivially copy constructible, just memcpy control and slot
1103- // else do like grow_capacity
1104- if (hud::is_constant_evaluated () || !hud::is_bitwise_copy_constructible_v<slot_type>)
1100+ if (count_ > 0 )
11051101 {
1106- // Set control to empty ending with sentinel
1107- hud::memory::set_memory (control_ptr_, control_size, empty_byte);
1108- control_ptr_[max_slot_count_] = sentinel_byte;
1109-
1110- // Nothing to copy, stop here
1111- if (other.count () == 0 )
1112- return *this ;
1113-
1114- // Copy slots to newly allocated buffer
11151102 control_type *control_full_or_sentinel = other.control_ptr_ ;
11161103 slot_type *slot_full_or_sentinel = other.slot_ptr_ ;
11171104 while (control_full_or_sentinel != other.control_ptr_sentinel ())
@@ -1131,48 +1118,33 @@ namespace hud
11311118 control_full_or_sentinel = full_or_sentinel;
11321119 }
11331120 }
1134- else
1135- {
1136- hud::memory::copy_construct_array (control_ptr_, other.control_ptr_ , control_size);
1137- if (other.count () > 0 )
1138- {
1139- hud::memory::copy_construct_array (slot_ptr_, other.slot_ptr_ , other.max_count ());
1140- }
1141- }
11421121 }
1143- else
1122+ else // If we don't have enough memory
11441123 {
1145- destroy_all_slots ();
1146- hud::memory::set_memory (control_ptr_, control_size_for_max_count (max_slot_count_), empty_byte);
1147- control_ptr_[max_slot_count_] = sentinel_byte;
1124+ // Free the control and slot allocation
1125+ free_control_and_slot (control_ptr_, slot_ptr_, max_slot_count_);
11481126
1149- // Copy controls
1127+ // Copy the allocator if copy_when_container_copy_assigned is true
11501128 if constexpr (hud::allocator_traits<allocator_t >::copy_when_container_copy_assigned::value)
11511129 {
11521130 allocator_ = other.allocator_ ;
11531131 }
1132+ // Copy the number of element
11541133 count_ = other.count_ ;
1134+ // Copy the max number of element
1135+ max_slot_count_ = compute_max_count (count_);
1136+ // Compute the free slot count before growing
11551137 free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
1138+ // Allocate the control and slot
1139+ usize control_size {allocate_control_and_slot (max_slot_count_)};
11561140
1157- usize control_size {control_size_for_max_count (max_slot_count_)};
1141+ // Set control to empty ending with sentinel
1142+ hud::memory::set_memory (control_ptr_, control_size, empty_byte);
1143+ control_ptr_[max_slot_count_] = sentinel_byte;
11581144
1159- // If constant evaluated context or when slot_type is not bitwise copy constructible
1160- // loop through all slot and construct them regardless of the trivially constructible ( Maybe only for control_ptr_ ) like like grow_capacity
1161- // In a non constant evaluated context
1162- // If type is trivially copy constructible, just memcpy control and slot
1163- // else do like grow_capacity
1164- if (hud::is_constant_evaluated () || !hud::is_bitwise_copy_constructible_v<slot_type>)
1145+ // If we have elements to copy, copy them
1146+ if (count_ > 0 )
11651147 {
1166-
1167- // Set control to empty ending with sentinel
1168- hud::memory::set_memory (control_ptr_, control_size, empty_byte);
1169- control_ptr_[max_slot_count_] = sentinel_byte;
1170-
1171- // Nothing to copy, stop here
1172- if (other.count () == 0 )
1173- return *this ;
1174-
1175- // Copy slots to newly allocated buffer
11761148 control_type *control_full_or_sentinel = other.control_ptr_ ;
11771149 slot_type *slot_full_or_sentinel = other.slot_ptr_ ;
11781150 while (control_full_or_sentinel != other.control_ptr_sentinel ())
@@ -1192,20 +1164,14 @@ namespace hud
11921164 control_full_or_sentinel = full_or_sentinel;
11931165 }
11941166 }
1195- else
1196- {
1197- hud::memory::copy_construct_array (control_ptr_, other.control_ptr_ , control_size);
1198- if (other.count () > 0 )
1199- {
1200- hud::memory::copy_construct_array (slot_ptr_, other.slot_ptr_ , other.max_count ());
1201- }
1202- }
12031167 }
12041168 return *this ;
12051169 }
12061170
12071171 /* * Reserve memory for at least `count` element and regenerates the hash table. */
1208- constexpr void reserve (usize count) noexcept
1172+ constexpr void
1173+ reserve (usize count) noexcept
1174+
12091175 {
12101176 if (count > max_slot_count_)
12111177 {
0 commit comments