1313#include " ../traits/is_trivially_copy_constructible.h"
1414#include " tuple_size.h"
1515#include " tuple_element.h"
16- #include " compressed_pair.h"
1716#include " ../traits/is_transparent.h"
1817#include " ../traits/conditional.h"
18+ #include " compressed_tuple.h"
1919
2020// TODO:
2121// Move common to a common class that contains max_slot_count_, count_, control_ptr_, slot_ptr_ and free_slot_before_grow_
@@ -842,7 +842,7 @@ namespace hud
842842 explicit constexpr hashset_impl () noexcept = default;
843843
844844 constexpr explicit hashset_impl (const allocator_type &allocator) noexcept
845- : allocator_ {allocator}
845+ : compressed_ {allocator, 0 }
846846 {
847847 }
848848
@@ -859,10 +859,9 @@ namespace hud
859859
860860 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
861861 constexpr explicit hashset_impl (const hashset_impl<u_storage_t , u_hasher_t , u_key_equal_t , u_allocator_t > &other, const allocator_type &allocator) noexcept
862- : allocator_ {allocator}
863- , max_slot_count_ {other.max_count ()}
862+ : max_slot_count_ {other.max_count ()}
864863 , count_ {other.count ()}
865- , free_slot_before_grow_( other.free_slot_before_grow_)
864+ , compressed_ {allocator, other.free_slot_before_grow_compressed ()}
866865 {
867866 copy_construct (other);
868867 }
@@ -875,10 +874,9 @@ namespace hud
875874
876875 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
877876 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
878- : allocator_ {allocator}
879- , max_slot_count_ {normalize_max_count (other.max_count () + extra_max_count)}
877+ : max_slot_count_ {normalize_max_count (other.max_count () + extra_max_count)}
880878 , count_ {other.count ()}
881- , free_slot_before_grow_( max_slot_before_grow(max_slot_count_) - count_)
879+ , compressed_ {allocator, max_slot_before_grow (max_slot_count_) - count_}
882880 {
883881 copy_construct (other, extra_max_count);
884882 }
@@ -891,10 +889,9 @@ namespace hud
891889
892890 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
893891 constexpr explicit hashset_impl (hashset_impl<u_storage_t , u_hasher_t , u_key_equal_t , u_allocator_t > &&other, const allocator_type &allocator) noexcept
894- : allocator_ {allocator}
895- , max_slot_count_ {other.max_count ()}
892+ : max_slot_count_ {other.max_count ()}
896893 , count_ {other.count ()}
897- , free_slot_before_grow_( other.free_slot_before_grow_)
894+ , compressed_ {allocator, other.free_slot_before_grow_compressed ()}
898895 {
899896 move_construct (hud::forward<hashset_impl<u_storage_t , u_hasher_t , u_key_equal_t , u_allocator_t >>(other));
900897 }
@@ -907,10 +904,9 @@ namespace hud
907904
908905 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
909906 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
910- : allocator_ {allocator}
911- , max_slot_count_ {normalize_max_count (other.max_count () + extra_max_count)}
907+ : max_slot_count_ {normalize_max_count (other.max_count () + extra_max_count)}
912908 , count_ {other.count ()}
913- , free_slot_before_grow_( max_slot_before_grow(max_slot_count_) - count_)
909+ , compressed_ {allocator, max_slot_before_grow (max_slot_count_) - count_}
914910 {
915911 move_construct (hud::forward<hashset_impl<u_storage_t , u_hasher_t , u_key_equal_t , u_allocator_t >>(other), extra_max_count);
916912 }
@@ -1072,14 +1068,14 @@ namespace hud
10721068
10731069 if constexpr (hud::allocator_traits<allocator_type>::swap_when_container_swap::value)
10741070 {
1075- hud::swap (allocator_ ( ), other.allocator_ ( ));
1071+ hud::swap (hud::get< 0 >(compressed_ ), hud::get< 0 >( other.compressed_ ));
10761072 }
10771073
10781074 hud::swap (other.count_ , count_);
10791075 hud::swap (other.control_ptr_ , control_ptr_);
10801076 hud::swap (other.slot_ptr_ , slot_ptr_);
10811077 hud::swap (other.max_slot_count_ , max_slot_count_);
1082- hud::swap (other.free_slot_before_grow_ , free_slot_before_grow_ );
1078+ hud::swap (other.free_slot_before_grow_compressed (), free_slot_before_grow_compressed () );
10831079 }
10841080
10851081 template <typename K>
@@ -1095,7 +1091,7 @@ namespace hud
10951091 /* * Retrieves the allocator. */
10961092 [[nodiscard]] HD_FORCEINLINE constexpr const allocator_type &allocator () const noexcept
10971093 {
1098- return allocator_ ;
1094+ return hud::get< 0 >(compressed_) ;
10991095 }
11001096
11011097 /* * Return the slack in number of elements. */
@@ -1311,12 +1307,12 @@ namespace hud
13111307 if (should_be_mark_as_empty_if_deleted (index))
13121308 {
13131309 control::set (control_ptr_, index, empty_byte, max_slot_count_);
1314- free_slot_before_grow_ ++;
1310+ free_slot_before_grow_compressed () ++;
13151311 }
13161312 else
13171313 {
13181314 control::set (control_ptr_, index, deleted_byte, max_slot_count_);
1319- free_slot_before_grow_ |= ~((~usize {}) >> 1 ); // Set the sign bit that represent the presence of delete slots
1315+ free_slot_before_grow_compressed () |= ~((~usize {}) >> 1 ); // Set the sign bit that represent the presence of delete slots
13201316 }
13211317 count_--;
13221318 }
@@ -1422,7 +1418,7 @@ namespace hud
14221418 other.slot_ptr_ = nullptr ;
14231419 other.max_slot_count_ = 0 ;
14241420 other.count_ = 0 ;
1425- other.free_slot_before_grow_ = 0 ;
1421+ other.free_slot_before_grow_compressed () = 0 ;
14261422 }
14271423 }
14281424
@@ -1448,12 +1444,12 @@ namespace hud
14481444 // Copy the allocator if copy_when_container_copy_assigned is true
14491445 if constexpr (hud::is_not_same_v<u_allocator_t , allocator_type> || hud::allocator_traits<allocator_t >::copy_when_container_copy_assigned::value)
14501446 {
1451- allocator_ = other.allocator_ ;
1447+ hud::get< 0 >(compressed_) = hud::get< 0 >( other.compressed_ ) ;
14521448 }
14531449 // Copy the number of element
14541450 count_ = other.count_ ;
14551451 // Compute the free slot count before growing
1456- free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
1452+ free_slot_before_grow_compressed () = max_slot_before_grow (max_slot_count_) - count_;
14571453 }
14581454 else // If we don't have enough memory
14591455 {
@@ -1463,14 +1459,14 @@ namespace hud
14631459 // Copy the allocator if copy_when_container_copy_assigned is true
14641460 if constexpr (hud::is_not_same_v<u_allocator_t , allocator_type> || hud::allocator_traits<allocator_t >::copy_when_container_copy_assigned::value)
14651461 {
1466- allocator_ = other.allocator_ ;
1462+ hud::get< 0 >(compressed_) = hud::get< 0 >( other.compressed_ ) ;
14671463 }
14681464 // Copy the number of element
14691465 count_ = other.count_ ;
14701466 // Copy the max number of element
14711467 max_slot_count_ = normalize_max_count (count_);
14721468 // Compute the free slot count before growing
1473- free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
1469+ free_slot_before_grow_compressed () = max_slot_before_grow (max_slot_count_) - count_;
14741470 // Allocate the control and slot
14751471 usize control_size {allocate_control_and_slot (max_slot_count_)};
14761472
@@ -1524,12 +1520,12 @@ namespace hud
15241520 // Copy the allocator if copy_when_container_copy_assigned is true
15251521 if constexpr (hud::is_not_same_v<u_allocator_t , allocator_type> || hud::allocator_traits<allocator_t >::copy_when_container_copy_assigned::value)
15261522 {
1527- allocator_ = hud::move (other.allocator_ );
1523+ hud::get< 0 >(compressed_) = hud::move (hud::get< 0 >( other.compressed_ ) );
15281524 }
15291525 // Copy the number of element
15301526 count_ = other.count_ ;
15311527 // Compute the free slot count before growing
1532- free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
1528+ free_slot_before_grow_compressed () = max_slot_before_grow (max_slot_count_) - count_;
15331529 }
15341530 else // If we don't have enough memory
15351531 {
@@ -1539,14 +1535,14 @@ namespace hud
15391535 // Copy the allocator if copy_when_container_copy_assigned is true
15401536 if constexpr (hud::is_not_same_v<u_allocator_t , allocator_type> || hud::allocator_traits<allocator_t >::copy_when_container_copy_assigned::value)
15411537 {
1542- allocator_ = hud::move (other.allocator_ );
1538+ hud::get< 0 >(compressed_) = hud::move (hud::get< 0 >( other.compressed_ ) );
15431539 }
15441540 // Copy the number of element
15451541 count_ = other.count_ ;
15461542 // Copy the max number of element
15471543 max_slot_count_ = normalize_max_count (count_);
15481544 // Compute the free slot count before growing
1549- free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
1545+ free_slot_before_grow_compressed () = max_slot_before_grow (max_slot_count_) - count_;
15501546 // Allocate the control and slot
15511547 usize control_size {allocate_control_and_slot (max_slot_count_)};
15521548
@@ -1582,7 +1578,7 @@ namespace hud
15821578 // Move allocator and move members
15831579 if constexpr (hud::is_not_same_v<u_allocator_t , allocator_type> || hud::allocator_traits<allocator_t >::move_when_container_move_assigned::value)
15841580 {
1585- allocator_ = hud::move (other.allocator_ );
1581+ hud::get< 0 >(compressed_) = hud::move (hud::get< 0 >( other.compressed_ ) );
15861582 }
15871583 control_ptr_ = other.control_ptr_ ;
15881584 other.control_ptr_ = const_cast <control_type *>(&INIT_GROUP[16 ]);
@@ -1592,8 +1588,8 @@ namespace hud
15921588 other.count_ = 0 ;
15931589 max_slot_count_ = other.max_slot_count_ ;
15941590 other.max_slot_count_ = 0 ;
1595- free_slot_before_grow_ = other.free_slot_before_grow_ ;
1596- other.free_slot_before_grow_ = 0 ;
1591+ free_slot_before_grow_compressed () = other.free_slot_before_grow_compressed () ;
1592+ other.free_slot_before_grow_compressed () = 0 ;
15971593 }
15981594 }
15991595
@@ -1666,7 +1662,7 @@ namespace hud
16661662 count_++;
16671663 control::set (control_ptr_, slot_index, h2, max_slot_count_);
16681664
1669- free_slot_before_grow_ --;
1665+ free_slot_before_grow_compressed () --;
16701666 return iterator {control_ptr_ + slot_index, slot_ptr_ + slot_index}; // slot_index;
16711667 }
16721668
@@ -1694,7 +1690,7 @@ namespace hud
16941690 usize control_size {allocate_control_and_slot (max_slot_count_)};
16951691
16961692 // Update number of slot we should put into the table before a resizing rehash
1697- free_slot_before_grow_ = max_slot_before_grow (max_slot_count_) - count_;
1693+ free_slot_before_grow_compressed () = max_slot_before_grow (max_slot_count_) - count_;
16981694
16991695 // Set control to empty ending with sentinel
17001696 hud::memory::set_memory (control_ptr_, control_size, empty_byte);
@@ -1725,7 +1721,7 @@ namespace hud
17251721 [[nodiscard]] constexpr usize free_slot_before_grow () const noexcept
17261722 {
17271723 // Remove the sign bit that represent if the map contains deleted slots
1728- return free_slot_before_grow_ & ((~usize {}) >> 1 );
1724+ return free_slot_before_grow_compressed () & ((~usize {}) >> 1 );
17291725 }
17301726
17311727 /* * Retrieves the next capacity after a grow. */
@@ -1858,14 +1854,14 @@ namespace hud
18581854
18591855 if (hud::is_constant_evaluated ())
18601856 {
1861- control_ptr_ = allocator_ .template allocate <control_type>(control_size).data ();
1862- slot_ptr_ = allocator_ .template allocate <slot_type>(slots_size).data ();
1857+ control_ptr_ = hud::get< 0 >(compressed_) .template allocate <control_type>(control_size).data ();
1858+ slot_ptr_ = hud::get< 0 >(compressed_) .template allocate <slot_type>(slots_size).data ();
18631859 }
18641860 else
18651861 {
18661862 // Allocate control, slot, and slot size to satisfy slot_ptr_ alignment requirements
18671863 const usize aligned_allocation_size {control_size + sizeof (slot_type) + slots_size};
1868- control_ptr_ = allocator_ .template allocate <control_type>(aligned_allocation_size).data ();
1864+ control_ptr_ = hud::get< 0 >(compressed_) .template allocate <control_type>(aligned_allocation_size).data ();
18691865 slot_ptr_ = reinterpret_cast <slot_type *>(hud::memory::align_address (reinterpret_cast <const uptr>(control_ptr_ + control_size), sizeof (slot_type)));
18701866 hud::check (hud::memory::is_pointer_aligned (slot_ptr_, alignof (slot_type)));
18711867 }
@@ -1883,13 +1879,13 @@ namespace hud
18831879 // and allocation is done in two separate allocation
18841880 if (hud::is_constant_evaluated ())
18851881 {
1886- allocator_ .template free <control_type>({control_ptr, control_size});
1887- allocator_ .template free <slot_type>({slot_ptr, slots_size});
1882+ hud::get< 0 >(compressed_) .template free <control_type>({control_ptr, control_size});
1883+ hud::get< 0 >(compressed_) .template free <slot_type>({slot_ptr, slots_size});
18881884 }
18891885 else
18901886 {
18911887 const usize aligned_allocation_size {control_size + sizeof (slot_type) + slots_size};
1892- allocator_ .template free <control_type>({control_ptr, aligned_allocation_size});
1888+ hud::get< 0 >(compressed_) .template free <control_type>({control_ptr, aligned_allocation_size});
18931889 }
18941890 }
18951891 }
@@ -1900,7 +1896,7 @@ namespace hud
19001896 control_ptr_ = const_cast <control_type *>(&INIT_GROUP[16 ]);
19011897 max_slot_count_ = 0 ;
19021898 count_ = 0 ;
1903- free_slot_before_grow_ = 0 ;
1899+ free_slot_before_grow_compressed () = 0 ;
19041900 }
19051901
19061902 constexpr void destroy_all_slots () noexcept
@@ -1955,9 +1951,27 @@ namespace hud
19551951 }
19561952 }
19571953
1954+ [[nodiscard]] constexpr usize &free_slot_before_grow_compressed () noexcept
1955+ {
1956+ return hud::get<1 >(compressed_);
1957+ }
1958+
1959+ [[nodiscard]] constexpr const usize &free_slot_before_grow_compressed () const noexcept
1960+ {
1961+ return hud::get<1 >(compressed_);
1962+ }
1963+
19581964 private:
1965+ /* * Max count of slot in the map. Always a power of two mask value. */
1966+ usize max_slot_count_ {0 };
1967+
1968+ /* * The count of values in the hashmap. */
1969+ usize count_ {0 };
1970+
1971+ hud::compressed_tuple<allocator_type, usize> compressed_ {hud::tag_init};
1972+
19591973 /* * The allocator. */
1960- allocator_type allocator_;
1974+ // allocator_type allocator_;
19611975
19621976 /* * The hasher function. */
19631977 hasher_type hasher_;
@@ -1971,14 +1985,8 @@ namespace hud
19711985 /* * Pointer to the slot segment. */
19721986 slot_type *slot_ptr_ {nullptr };
19731987
1974- /* * Max count of slot in the map. Always a power of two mask value. */
1975- usize max_slot_count_ {0 };
1976-
1977- /* * The count of values in the hashmap. */
1978- usize count_ {0 };
1979-
19801988 /* * Number of slot we should put into the table before a resizing rehash. */
1981- usize free_slot_before_grow_ {0 };
1989+ // usize free_slot_before_grow_ {0};
19821990 };
19831991
19841992 } // namespace details::hashset
0 commit comments