2323// Add hasher and equal object added in compressed_pair like compressed_pair<allocator, compressed_pair<hasher, compressed_pair<equal, common>>>
2424// Maybe create a compressed_tuple? ;)
2525
26+ // Hashset
27+ // Difference with STL:
28+ // - Don't use is_transparent because we don't have the nessecity to keep compatibility with existing code.
29+ // Comparaison and hasher is always transparent if the user provide a custom equal or hasher type.
30+
2631namespace hud
2732{
2833 namespace details ::hashset
@@ -281,50 +286,6 @@ namespace hud
281286 key_type element_;
282287 };
283288
284- // /**
285- // * A default hasher struct for hashing keys.
286- // * This struct provides a mechanism to hash key and combine them with the current hasher value.
287- // *
288- // * @tparam key_t The type of the key to be hashed.
289- // */
290- // struct default_hasher
291- // {
292- // using is_transparent = void;
293-
294- // /**
295- // * Operator to hash the value and combine it with the current hasher value.
296- // * This function uses variadic templates to accept multiple arguments.
297- // * @tparam type_t Types of the arguments to hash.
298- // * @param values Arguments to hash.
299- // * @return A 64-bit hash value.
300- // */
301- // template<typename... type_t>
302- // [[nodiscard]] constexpr u64 operator()(type_t &&...values) noexcept
303- // {
304- // return hud::hash_64<hud::decay_t<type_t>...> {}(hud::forward<type_t>(values)...);
305- // }
306-
307- // /**
308- // * Function to hash the value and combine it with the current hasher value.
309- // * This function uses variadic templates to accept multiple arguments.
310- // * @tparam type_t Types of the arguments to hash.
311- // * @param values Arguments to hash.
312- // * @return A 64-bit hash value.
313- // */
314- // template<typename... type_t>
315- // [[nodiscard]] constexpr u64 hash(type_t &&...values) noexcept
316- // {
317- // return (*this)(hud::forward<type_t>(values)...);
318- // }
319- // };
320-
321- // template<typename key_t>
322- // struct default_equal
323- // : hud::equal<key_t>
324- // {
325- // using is_transparent = void;
326- // };
327-
328289 using default_allocator = hud::heap_allocator;
329290
330291 /* * Retrives the H1 (57 first bit) of a hash. */
@@ -824,11 +785,10 @@ namespace hud
824785 /* * The type of allocation done by the allocator. */
825786 using memory_allocation_type = typename allocator_type::template memory_allocation_type<slot_type>;
826787
827- template <typename K>
828- using key_arg_type = typename KeyArg<hud::is_transparent_v<hasher_type> && hud::is_transparent_v<key_equal_type>>::template type<K, key_type>;
829-
830788 static_assert (hud::is_hashable_64_v<key_type>, " key_type is not hashable" );
831789 static_assert (hud::is_comparable_with_equal_v<key_type, key_type>, " key_type is not comparable with equal" );
790+ template <typename K>
791+ using key_arg_type = typename KeyArg<hud::is_hashable_64_v<K> && hud::is_comparable_with_equal_v<key_type, K>>::template type<K, key_type>;
832792
833793 template <typename u_storage_t , typename u_hasher_t , typename u_key_equal_t , typename u_allocator_t >
834794 friend class hashset_impl ; // Friend with other hashset_impl of other types
@@ -1005,36 +965,13 @@ namespace hud
1005965 /* * Find a key and return an iterator to the value. */
1006966 template <typename K>
1007967 [[nodiscard]]
1008- constexpr iterator find (const K &key) noexcept
968+ constexpr iterator find (K & &key) noexcept
1009969 {
1010- u64 hash {hasher_ (key)};
1011- u64 h1 (H1 (hash));
1012- hud::check (hud::bits::is_valid_power_of_two_mask (max_slot_count_) && " Not a mask" );
1013- usize slot_index (h1 & max_slot_count_);
1014- while (true )
970+ if constexpr (hud::is_hashable_64_v<K> && hud::is_comparable_with_equal_v<key_type, K>)
1015971 {
1016- group_type group {control_ptr_ + slot_index};
1017- group_type::mask group_mask_that_match_h2 {group.match (H2 (hash))};
1018- for (u32 group_index_that_match_h2 : group_mask_that_match_h2)
1019- {
1020- usize slot_index_that_match_h2 {slot_index + group_index_that_match_h2 & max_slot_count_};
1021- slot_type *slot_that_match_h2 {slot_ptr_ + slot_index_that_match_h2};
1022- if (key_equal_ (slot_that_match_h2->key (), key)) [[likely]]
1023- {
1024- return {control_ptr_ + slot_index_that_match_h2, slot_that_match_h2};
1025- }
1026- }
1027-
1028- // If we have free slot, we don't find it
1029- if (group.mask_of_empty_slot ().has_empty_slot ())
1030- {
1031- return iterator {control_ptr_sentinel ()};
1032- }
1033-
1034- // Advance to next group (Maybe a control iterator that iterate over groups can be better alternative)
1035- slot_index += group_type::SLOT_PER_GROUP ;
1036- slot_index &= max_slot_count_;
972+ return find_impl (hud::forward<K>(key));
1037973 }
974+ return find_impl (key_type (key));
1038975 }
1039976
1040977 constexpr void rehash (i32 count) noexcept
@@ -1067,25 +1004,25 @@ namespace hud
10671004 rehash (0 );
10681005 }
10691006
1070- template <typename K = key_type >
1007+ template <typename K>
10711008 [[nodiscard]]
1072- constexpr const_iterator find (const key_arg_type<K> &key) const noexcept
1009+ constexpr const_iterator find (K & &key) const noexcept
10731010 {
1074- return const_cast <hashset_impl *>(this )->find (key);
1011+ return const_cast <hashset_impl *>(this )->find (hud::forward<K>( key) );
10751012 }
10761013
1077- template <typename K = key_type >
1014+ template <typename K>
10781015 [[nodiscard]]
1079- constexpr bool contains (const key_arg_type<K> &key) noexcept
1016+ constexpr bool contains (K & &key) noexcept
10801017 {
1081- return find (key) != end ();
1018+ return find (hud::forward<K>( key) ) != end ();
10821019 }
10831020
1084- template <typename K = key_type >
1021+ template <typename K>
10851022 [[nodiscard]]
1086- constexpr bool contains (const key_arg_type<K> &key) const noexcept
1023+ constexpr bool contains (K & &key) const noexcept
10871024 {
1088- return find (key) != end ( );
1025+ return const_cast <hashset_impl *>( this )-> contains (hud::forward<K>(key) );
10891026 }
10901027
10911028 constexpr void swap (hashset_impl &other) noexcept
@@ -1105,10 +1042,10 @@ namespace hud
11051042 hud::swap (other.free_slot_before_grow_ , free_slot_before_grow_);
11061043 }
11071044
1108- template <typename K = key_type >
1109- constexpr void remove (const key_arg_type<K> &key) noexcept
1045+ template <typename K>
1046+ constexpr void remove (K & &key) noexcept
11101047 {
1111- iterator it = find (key);
1048+ iterator it = find (hud::forward<K>( key) );
11121049 if (it != end ())
11131050 {
11141051 remove_iterator (it);
@@ -1174,10 +1111,11 @@ namespace hud
11741111
11751112 protected:
11761113 /* *
1177- * Insert a key in the hashset and pass
1178- * @param key The key associated with the `value`
1179- * @param args List of arguments pass to `value_type` constructor after the `key` itself
1180- * @return Iterator to the `value`
1114+ * Finds or inserts a slot corresponding to the given key.
1115+ * If the key is not found, a new slot is created by constructing it with the key followed by `args`.
1116+ * @param key The key used to find or insert the slot.
1117+ * @param args The arguments forwarded to the `slot_type` constructor after the key.
1118+ * @return An iterator to the inserted or existing value.
11811119 */
11821120 template <typename ... args_t >
11831121 requires (hud::is_constructible_v<slot_type, key_type, args_t ...>)
@@ -1193,10 +1131,11 @@ namespace hud
11931131 }
11941132
11951133 /* *
1196- * Insert a key in the hashset.
1197- * @param key The key associated with the `value`
1198- * @param args List of arguments pass to `value_type` constructor after the `key` itself
1199- * @return Iterator to the `value`
1134+ * Finds or inserts a slot corresponding to the given key.
1135+ * If the key is not found, a new slot is created by constructing it with the key followed by `args`.
1136+ * @param key The key used to find or insert the slot.
1137+ * @param args The arguments forwarded to the `slot_type` constructor after the key.
1138+ * @return An iterator to the inserted or existing value.
12001139 */
12011140 template <typename ... args_t >
12021141 requires (hud::is_constructible_v<slot_type, const key_type &, args_t ...>)
@@ -1212,14 +1151,48 @@ namespace hud
12121151 }
12131152
12141153 private:
1215- template <typename u_key_type>
1216- [[nodiscard]] constexpr u64 compute_hash (const u_key_type &key) noexcept
1154+ template <typename K>
1155+ [[nodiscard]]
1156+ constexpr iterator find_impl (K &&key) noexcept
1157+ {
1158+ u64 hash {hasher_ (hud::forward<K>(key))};
1159+ u64 h1 (H1 (hash));
1160+ hud::check (hud::bits::is_valid_power_of_two_mask (max_slot_count_) && " Not a mask" );
1161+ usize slot_index (h1 & max_slot_count_);
1162+ while (true )
1163+ {
1164+ group_type group {control_ptr_ + slot_index};
1165+ group_type::mask group_mask_that_match_h2 {group.match (H2 (hash))};
1166+ for (u32 group_index_that_match_h2 : group_mask_that_match_h2)
1167+ {
1168+ usize slot_index_that_match_h2 {slot_index + group_index_that_match_h2 & max_slot_count_};
1169+ slot_type *slot_that_match_h2 {slot_ptr_ + slot_index_that_match_h2};
1170+ if (key_equal_ (slot_that_match_h2->key (), hud::forward<K>(key))) [[likely]]
1171+ {
1172+ return {control_ptr_ + slot_index_that_match_h2, slot_that_match_h2};
1173+ }
1174+ }
1175+
1176+ // If we have free slot, we don't find it
1177+ if (group.mask_of_empty_slot ().has_empty_slot ())
1178+ {
1179+ return iterator {control_ptr_sentinel ()};
1180+ }
1181+
1182+ // Advance to next group (Maybe a control iterator that iterate over groups can be better alternative)
1183+ slot_index += group_type::SLOT_PER_GROUP ;
1184+ slot_index &= max_slot_count_;
1185+ }
1186+ }
1187+
1188+ template <typename K>
1189+ [[nodiscard]] constexpr u64 compute_hash (const K &key) noexcept
12171190 {
1218- if constexpr (hud::is_same_v<key_type, u_key_type >)
1191+ if constexpr (hud::is_same_v<key_type, K >)
12191192 {
12201193 return hasher_ (key);
12211194 }
1222- return hasher_ (key_type { key} );
1195+ return hasher_ (key_type ( key) );
12231196 }
12241197
12251198 constexpr bool should_be_mark_as_empty_if_deleted (usize index) const noexcept
0 commit comments