1313#include " ../traits/is_trivially_copy_constructible.h"
1414#include " tuple_size.h"
1515#include " tuple_element.h"
16+ #include " compressed_pair.h"
17+
18+ // TODO:
19+ // Move common to a common class that contains max_slot_count_, count_, control_ptr_, slot_ptr_ and free_slot_before_grow_
20+ // Use compressed_pair with allocator and the common object
21+ // Add hasher and equal object added in compressed_pair like compressed_pair<allocator, compressed_pair<hasher, compressed_pair<equal, common>>>
22+ // Maybe create a compressed_tuple? ;)
1623
1724namespace hud
1825{
@@ -819,7 +826,7 @@ namespace hud
819826 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
820827 constexpr explicit hashset_impl (const hashset_impl<u_storage_t , u_hasher_t , u_key_equal_t , u_allocator_t > &other, usize extra_max_count, const allocator_type &allocator) noexcept
821828 : allocator_ {allocator}
822- , max_slot_count_ {compute_max_count (other.max_count () + extra_max_count)}
829+ , max_slot_count_ {normalize_max_count (other.max_count () + extra_max_count)}
823830 , count_ {other.count ()}
824831 , free_slot_before_grow_(max_slot_before_grow(max_slot_count_) - count_)
825832 {
@@ -851,7 +858,7 @@ namespace hud
851858 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
852859 constexpr explicit hashset_impl (hashset_impl<u_storage_t , u_hasher_t , u_key_equal_t , u_allocator_t > &&other, usize extra_max_count, const allocator_type &allocator) noexcept
853860 : allocator_ {allocator}
854- , max_slot_count_ {compute_max_count (other.max_count () + extra_max_count)}
861+ , max_slot_count_ {normalize_max_count (other.max_count () + extra_max_count)}
855862 , count_ {other.count ()}
856863 , free_slot_before_grow_(max_slot_before_grow(max_slot_count_) - count_)
857864 {
@@ -912,12 +919,13 @@ namespace hud
912919 return *this ;
913920 }
914921
915- /* * Reserve memory for at least `count` element and regenerates the hash table. */
922+ /* * Reserve memory for at least `count` element and regenerates the hash table if needed . */
916923 constexpr void reserve (usize count) noexcept
917924 {
918- if (count > max_slot_count_)
925+ const usize max_count = normalize_max_count (min_capacity_for_count (count));
926+ if (max_count > max_slot_count_)
919927 {
920- resize (compute_max_count (count) );
928+ resize (max_count );
921929 }
922930 }
923931
@@ -1041,7 +1049,7 @@ namespace hud
10411049 // We request 0 or more and we have allocation and elements
10421050 // bitor is a faster way of doing `max` here. We will round up to the next
10431051 // power-of-2-minus-1, so bitor is good enough.
1044- usize max_count = compute_max_count (count | min_capacity_for_count (count_));
1052+ usize max_count = normalize_max_count (count | min_capacity_for_count (count_));
10451053 if (count == 0 || max_count > max_slot_count_)
10461054 resize (max_count);
10471055 }
@@ -1069,6 +1077,23 @@ namespace hud
10691077 return find (key) != end ();
10701078 }
10711079
1080+ constexpr void swap (hashset_impl &other) noexcept
1081+ requires(hud::is_swappable_v<slot_type>)
1082+ {
1083+ static_assert (hud::is_nothrow_swappable_v<allocator_type>, " swap(hashmap<type_t>&) is throwable. hashmap is not designed to allow throwable swappable components" );
1084+
1085+ if constexpr (hud::allocator_traits<allocator_type>::swap_when_container_swap::value)
1086+ {
1087+ hud::swap (allocator_ (), other.allocator_ ());
1088+ }
1089+
1090+ hud::swap (other.count_ , count_);
1091+ hud::swap (other.control_ptr_ , control_ptr_);
1092+ hud::swap (other.slot_ptr_ , slot_ptr_);
1093+ hud::swap (other.max_slot_count_ , max_slot_count_);
1094+ hud::swap (other.free_slot_before_grow_ , free_slot_before_grow_);
1095+ }
1096+
10721097 constexpr void remove (const key_type &key) noexcept
10731098 {
10741099 iterator it = find (key);
@@ -1321,7 +1346,7 @@ namespace hud
13211346 // Copy the number of element
13221347 count_ = other.count_ ;
13231348 // Copy the max number of element
1324- max_slot_count_ = compute_max_count (count_);
1349+ max_slot_count_ = normalize_max_count (count_);
13251350 // Compute the free slot count before growing
13261351 free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
13271352 // Allocate the control and slot
@@ -1397,7 +1422,7 @@ namespace hud
13971422 // Copy the number of element
13981423 count_ = other.count_ ;
13991424 // Copy the max number of element
1400- max_slot_count_ = compute_max_count (count_);
1425+ max_slot_count_ = normalize_max_count (count_);
14011426 // Compute the free slot count before growing
14021427 free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
14031428 // Allocate the control and slot
@@ -1493,7 +1518,7 @@ namespace hud
14931518 [[nodiscard]] constexpr usize insert_no_construct (u64 h1, u8 h2) noexcept
14941519 {
14951520 // If we reach the load factor grow the table and retrieves the new slot, else use the given slot
1496- // TODO : check rehash_and_grow_if_necessary and implement the SQuash DELETED branch
1521+ // TODO : check rehash_and_grow_if_necessary and implement the Squash DELETED branch
14971522 if (free_slot_before_grow () == 0 )
14981523 {
14991524 resize (next_capacity ());
@@ -1512,7 +1537,7 @@ namespace hud
15121537 constexpr void resize (usize new_max_slot_count) noexcept
15131538 {
15141539 // hud::check(new_max_slot_count > max_slot_count_ && "Grow need a bigger value");
1515- hud::check (hud::bits::is_valid_power_of_two_mask (max_slot_count_ ) && " Not a mask" );
1540+ hud::check (hud::bits::is_valid_power_of_two_mask (new_max_slot_count ) && " Not a mask" );
15161541
15171542 // Create the buffer with control and slots
15181543 // Slots are aligned based on alignof(slot_type)
@@ -1575,10 +1600,10 @@ namespace hud
15751600 return max_slot_count_ * 2 + 1 ;
15761601 }
15771602
1578- /* * Retrieves the max slot count for the given count . */
1579- [[nodiscard]] constexpr usize compute_max_count (usize count ) const noexcept
1603+ /* * Retrieves a correct max slot count that is applicable . */
1604+ [[nodiscard]] constexpr usize normalize_max_count (usize max_slot_count ) const noexcept
15801605 {
1581- return count ? ~usize {} >> hud::bits::leading_zeros (count ) : 0 ;
1606+ return max_slot_count ? ~usize {} >> hud::bits::leading_zeros (max_slot_count ) : 0 ;
15821607 }
15831608
15841609 /* * Compute the size of the allocation needed for the given slot count. */
@@ -1653,7 +1678,10 @@ namespace hud
16531678 capacity - capacity / 8 ;
16541679 }
16551680
1656- /* * Compute the minimum capacity needed for the given `count` element that respect the load factor */
1681+ /* *
1682+ * Compute the minimum capacity needed for the given `count` element that respect the load factor.
1683+ * The capacity can be invalid, you should call
1684+ */
16571685 [[nodiscard]] constexpr usize min_capacity_for_count (usize count) const noexcept
16581686 {
16591687 // `count*8/7`
@@ -1786,7 +1814,7 @@ namespace hud
17861814 }
17871815
17881816 private:
1789- /* * The allocator. */
1817+ // / ** The allocator. */
17901818 allocator_type allocator_;
17911819
17921820 /* * The control of the hashmap. Initialized to sentinel. */
@@ -1873,6 +1901,12 @@ namespace hud
18731901 using type = const typename details::hashset::slot<key_t >::key_type;
18741902 };
18751903
1904+ template <typename key_t , typename hasher_t , typename key_equal_t , typename allocator_t >
1905+ constexpr void swap (hashset<key_t , hasher_t , key_equal_t , allocator_t > &first, hashset<key_t , hasher_t , key_equal_t , allocator_t > &second) noexcept
1906+ {
1907+ first.swap (second);
1908+ }
1909+
18761910} // namespace hud
18771911
18781912namespace std
0 commit comments