Skip to content

Commit 5fd5235

Browse files
author
Julian LALU
committed
Improve Hashset
1 parent b564097 commit 5fd5235

File tree

5 files changed

+234
-27
lines changed

5 files changed

+234
-27
lines changed

interface/core/containers/hashmap.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,19 @@ namespace hud
154154
static_assert(hud::is_nothrow_constructible_v<pair_type, u_key_t, u_value_t>);
155155
}
156156

157+
/**
158+
* Constructor that initializes the hashmap_storage with a key and a value.
159+
* @tparam u_key_t Type of the key.
160+
* @tparam u_value_t Type of the value.
161+
* @param key The key to initialize with.
162+
* @param value The value to initialize with.
163+
*/
164+
template<typename key_tuple_t, typename value_tuple_t>
165+
constexpr explicit hashmap_storage(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple) noexcept
166+
: element_(hud::tag_piecewise_construct, hud::forward<key_tuple_t>(key_tuple), hud::forward<value_tuple_t>(value_tuple))
167+
{
168+
}
169+
157170
/**
158171
* Copy assign.
159172
* Does not accept throwable copy constructible components.
@@ -249,7 +262,7 @@ namespace hud
249262
using value_type = typename storage_type::value_type;
250263

251264
/** Inherit constructors and methods from the base class. */
252-
using super::add;
265+
// using super::add;
253266
using super::reserve;
254267
using super::super;
255268
using typename super::allocator_type;
@@ -327,7 +340,7 @@ namespace hud
327340
template<typename u_key_t = key_t, typename u_value_t = value_t>
328341
constexpr iterator add(hud::pair<u_key_t, u_value_t> &&pair) noexcept
329342
{
330-
return super::add(hud::get<0>(hud::forward<hud::pair<u_key_t, u_value_t>>(pair)), hud::get<1>(hud::forward<hud::pair<u_key_t, u_value_t>>(pair)));
343+
return super::add(hud::forward<u_key_t &&>(pair.first), hud::forward<u_value_t &&>(pair.second));
331344
}
332345

333346
/**
@@ -336,17 +349,17 @@ namespace hud
336349
* @param args List of arguments pass to `value_type` constructor after the `key` itself
337350
* @return Iterator to the `value`
338351
*/
339-
340-
constexpr iterator add(key_type &&key, value_type &&value) noexcept
341-
requires(hud::is_constructible_v<storage_type, key_type, value_type>)
352+
template<typename u_key_t = key_t, typename u_value_t = value_t>
353+
constexpr iterator add(u_key_t &&key, u_value_t &&value) noexcept
354+
requires(hud::is_constructible_v<storage_type, u_key_t, u_value_t>)
342355
{
343-
return super::add(hud::forward<key_type>(key), hud::forward<key_type>(value));
356+
return super::add(hud::forward<u_key_t>(key), hud::forward<u_value_t>(value));
344357
}
345358

346359
template<typename key_tuple_t, typename value_tuple_t>
347-
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t key_tuple, value_tuple_t value_tuple) noexcept
360+
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple) noexcept
348361
{
349-
// return super::add(hud::tag_piecewise_construct_t, key_tuple, value_tuple);
362+
return super::add(hud::tag_piecewise_construct, hud::forward<key_tuple_t>(key_tuple), hud::forward<value_tuple_t>(value_tuple));
350363
}
351364
};
352365

interface/core/containers/hashset.h

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,20 +1162,39 @@ namespace hud
11621162
* @param args The arguments forwarded to the `slot_type` constructor after the key.
11631163
* @return An iterator to the inserted or existing value.
11641164
*/
1165-
// template<typename key_tuple_t, typename value_tuple_t>
1166-
// requires(hud::is_constructible_v<slot_type, key_type, args_t...>)
1167-
// constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t key_tuple, value_tuple_t value_tuple) noexcept
1168-
// {
1169-
// hud::pair<usize, bool> res {find_or_insert_no_construct(key)};
1170-
// slot_type *slot_ptr {slot_ptr_ + res.first};
1171-
// if (res.second)
1172-
// {
1173-
// hud::memory::construct_object_at(slot_ptr, hud::move(key), hud::forward<args_t>(args)...);
1174-
// }
1175-
// return {control_ptr_ + res.first, slot_ptr};
1176-
// }
1165+
template<typename key_tuple_t, typename value_tuple_t>
1166+
requires(hud::is_hashable_64_v<key_type, key_tuple_t> && hud::is_comparable_with_equal_v<key_type, key_tuple_t>)
1167+
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple) noexcept
1168+
{
1169+
hud::pair<usize, bool> res = find_or_insert_no_construct(hud::forward<key_tuple_t>(key_tuple));
1170+
slot_type *slot_ptr {slot_ptr_ + res.first};
1171+
if (res.second)
1172+
{
1173+
hud::memory::construct_object_at(slot_ptr, hud::tag_piecewise_construct, hud::forward<key_tuple_t>(key_tuple), hud::forward<value_tuple_t>(value_tuple));
1174+
}
1175+
return {control_ptr_ + res.first, slot_ptr};
1176+
}
1177+
1178+
template<typename key_tuple_t, typename value_tuple_t>
1179+
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple) noexcept
1180+
{
1181+
return add(hud::tag_piecewise_construct, hud::forward<key_tuple_t>(key_tuple), hud::forward<value_tuple_t>(value_tuple), hud::make_index_sequence<hud::tuple_size_v<key_tuple_t>> {}, hud::make_index_sequence<hud::tuple_size_v<value_tuple_t>> {});
1182+
}
11771183

11781184
private:
1185+
template<typename key_tuple_t, usize... indices_key, typename value_tuple_t, usize... indices_value>
1186+
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple, hud::index_sequence<indices_key...>, hud::index_sequence<indices_value...>) noexcept
1187+
{
1188+
key_type key(hud::get<indices_key>(key_tuple)...);
1189+
hud::pair<usize, bool> res = find_or_insert_no_construct(key);
1190+
slot_type *slot_ptr {slot_ptr_ + res.first};
1191+
if (res.second)
1192+
{
1193+
hud::memory::construct_object_at(slot_ptr, hud::tag_piecewise_construct, hud::forward<key_tuple_t>(key_tuple), hud::forward<value_tuple_t>(value_tuple));
1194+
}
1195+
return {control_ptr_ + res.first, slot_ptr};
1196+
}
1197+
11791198
template<typename K>
11801199
[[nodiscard]]
11811200
constexpr iterator find_impl(K &&key) noexcept

interface/core/containers/pair.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,16 +279,16 @@ namespace hud
279279
* Constructs a `pair` from two tuples by unpacking their elements.
280280
* @tparam tuple_first Type of the first tuple.
281281
* @tparam tuple_second Type of the second tuple.
282-
* @tparam indexes_first Index sequence for elements to extract from the first tuple.
283-
* @tparam indexes_second Index sequence for elements to extract from the second tuple.
282+
* @tparam indicies_first Index sequence for elements to extract from the first tuple.
283+
* @tparam indicies_second Index sequence for elements to extract from the second tuple.
284284
* @param first_tuple Reference to the first tuple to move from.
285285
* @param second_tuple Reference to the second tuple to move from.
286286
* @param ... Index sequences used to unpack the tuple elements.
287287
*/
288-
template<typename tuple_first, typename tuple_second, usize... indexes_first, usize... indexes_second>
289-
constexpr pair(tuple_first &first_tuple, tuple_second &second_tuple, hud::index_sequence<indexes_first...>, hud::index_sequence<indexes_second...>) noexcept
290-
: first(hud::get<indexes_first>(hud::move(first_tuple))...)
291-
, second(hud::get<indexes_second>(hud::move(second_tuple))...)
288+
template<typename tuple_first, typename tuple_second, usize... indicies_first, usize... indicies_second>
289+
constexpr pair(tuple_first &first_tuple, tuple_second &second_tuple, hud::index_sequence<indicies_first...>, hud::index_sequence<indicies_second...>) noexcept
290+
: first(hud::get<indicies_first>(hud::move(first_tuple))...)
291+
, second(hud::get<indicies_second>(hud::move(second_tuple))...)
292292
{
293293
}
294294
};

test/hashmap/hashmap_add.cpp

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4990,14 +4990,143 @@ GTEST_TEST(hashmap, add_by_piecewise_construct_bitwise_same_type)
49904990
constexpr usize reserved_size = 2;
49914991
hashmap_type map;
49924992
map.reserve(reserved_size);
4993-
// map.add(hud::tag_piecewise_construct, hud::forward_as_tuple(1), hud::forward_as_tuple(2));
4993+
const auto it = map.add(hud::tag_piecewise_construct, hud::forward_as_tuple(1), hud::forward_as_tuple(2));
4994+
return hud::tuple {
4995+
map.count() == 1, // 0
4996+
it->key() == 1, // 1
4997+
it->value() == 2 // 2
4998+
};
4999+
};
5000+
5001+
// Non constant
5002+
{
5003+
const auto result = test();
5004+
hud_assert_true(hud::get<0>(result));
5005+
hud_assert_true(hud::get<1>(result));
5006+
hud_assert_true(hud::get<2>(result));
5007+
}
5008+
5009+
// Constant
5010+
{
5011+
constexpr auto result = test();
5012+
hud_assert_true(hud::get<0>(result));
5013+
hud_assert_true(hud::get<1>(result));
5014+
hud_assert_true(hud::get<2>(result));
5015+
}
5016+
}
5017+
5018+
GTEST_TEST(hashmap, add_by_piecewise_construct_bitwise_different_type)
5019+
{
5020+
using key_type = i32;
5021+
using value_type = i64;
5022+
using other_key_type = u32;
5023+
using other_value_type = u64;
5024+
using hashmap_type = hud::hashmap<key_type, value_type, hud::hash_64<key_type>, hud::equal<key_type>, hud_test::allocator_watcher<1>>;
5025+
5026+
const auto test = []()
5027+
{
5028+
constexpr usize reserved_size = 2;
5029+
hashmap_type map;
5030+
map.reserve(reserved_size);
5031+
const auto it = map.add(hud::tag_piecewise_construct, hud::forward_as_tuple(other_key_type {1}), hud::forward_as_tuple(other_value_type {2}));
5032+
5033+
return hud::tuple {
5034+
map.count() == 1, // 0
5035+
it->key() == 1, // 1
5036+
it->value() == 2 // 2
5037+
};
5038+
};
5039+
5040+
// Non constant
5041+
{
5042+
const auto result = test();
5043+
hud_assert_true(hud::get<0>(result));
5044+
hud_assert_true(hud::get<1>(result));
5045+
hud_assert_true(hud::get<2>(result));
5046+
}
5047+
5048+
// Constant
5049+
{
5050+
constexpr auto result = test();
5051+
hud_assert_true(hud::get<0>(result));
5052+
hud_assert_true(hud::get<1>(result));
5053+
hud_assert_true(hud::get<2>(result));
5054+
}
5055+
}
5056+
5057+
GTEST_TEST(hashmap, add_by_piecewise_construct_non_bitwise_same_type)
5058+
{
5059+
using key_type = hud_test::non_bitwise_type;
5060+
using value_type = hud_test::non_bitwise_type;
5061+
using hashmap_type = hud::hashmap<key_type, value_type, hud::hash_64<key_type>, hud::equal<key_type>, hud_test::allocator_watcher<1>>;
5062+
5063+
static_assert(hud::is_hashable_64_v<key_type, hud::tuple<i32, i32 *>>);
5064+
static_assert(hud::is_comparable_with_equal_v<key_type, hud::tuple<i32, i32 *>>);
5065+
5066+
const auto test = []()
5067+
{
5068+
constexpr usize reserved_size = 2;
5069+
i32 ptr[2];
5070+
hashmap_type map;
5071+
map.reserve(reserved_size);
5072+
const auto it = map.add(hud::tag_piecewise_construct, hud::forward_as_tuple(1, ptr), hud::forward_as_tuple(2, ptr + 1));
5073+
5074+
return hud::tuple {
5075+
map.count() == 1, // 0
5076+
it->key().constructor_count() == 1, // 1
5077+
it->key().move_constructor_count() == 0, // 2
5078+
it->key().copy_constructor_count() == 0, // 3
5079+
it->key().move_assign_count() == 0, // 4
5080+
it->key().copy_assign_count() == 0, // 5
5081+
it->key().id() == 1, // 6
5082+
it->key().destructor_counter() == ptr, // 7
5083+
it->value().constructor_count() == 1, // 8
5084+
it->value().move_constructor_count() == 0, // 9
5085+
it->value().copy_constructor_count() == 0, // 10
5086+
it->value().move_assign_count() == 0, // 11
5087+
it->value().copy_assign_count() == 0, // 12
5088+
it->value().id() == 2, // 13
5089+
it->value().destructor_counter() == ptr + 1 // 14
5090+
};
49945091
};
49955092

49965093
// Non constant
49975094
{
5095+
const auto result = test();
5096+
hud_assert_true(hud::get<0>(result));
5097+
hud_assert_true(hud::get<1>(result));
5098+
hud_assert_true(hud::get<2>(result));
5099+
hud_assert_true(hud::get<3>(result));
5100+
hud_assert_true(hud::get<4>(result));
5101+
hud_assert_true(hud::get<5>(result));
5102+
hud_assert_true(hud::get<6>(result));
5103+
hud_assert_true(hud::get<7>(result));
5104+
hud_assert_true(hud::get<8>(result));
5105+
hud_assert_true(hud::get<9>(result));
5106+
hud_assert_true(hud::get<10>(result));
5107+
hud_assert_true(hud::get<11>(result));
5108+
hud_assert_true(hud::get<12>(result));
5109+
hud_assert_true(hud::get<13>(result));
5110+
hud_assert_true(hud::get<14>(result));
49985111
}
49995112

50005113
// Constant
50015114
{
5115+
constexpr auto result = test();
5116+
hud_assert_true(hud::get<0>(result));
5117+
hud_assert_true(hud::get<1>(result));
5118+
hud_assert_true(hud::get<2>(result));
5119+
hud_assert_true(hud::get<3>(result));
5120+
hud_assert_true(hud::get<4>(result));
5121+
hud_assert_true(hud::get<5>(result));
5122+
hud_assert_true(hud::get<6>(result));
5123+
hud_assert_true(hud::get<7>(result));
5124+
hud_assert_true(hud::get<8>(result));
5125+
hud_assert_true(hud::get<9>(result));
5126+
hud_assert_true(hud::get<10>(result));
5127+
hud_assert_true(hud::get<11>(result));
5128+
hud_assert_true(hud::get<12>(result));
5129+
hud_assert_true(hud::get<13>(result));
5130+
hud_assert_true(hud::get<14>(result));
50025131
}
50035132
}

test/misc/non_bitwise_type.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define HD_INC_MISC_NON_BITWISE_TYPE_H
33
#include <core/minimal.h>
44
#include <core/templates/equal.h>
5+
#include <core/containers/tuple.h>
56

67
namespace hud_test
78
{
@@ -200,6 +201,11 @@ namespace hud_test
200201
return left.id() == id;
201202
}
202203

204+
[[nodiscard]] HD_FORCEINLINE constexpr bool operator==(const non_bitwise_type &left, const hud::tuple<i32, i32 *> &rhs) noexcept
205+
{
206+
return left.id() == hud::get<0>(rhs);
207+
}
208+
203209
static_assert(hud::is_move_constructible_v<non_bitwise_type>);
204210
static_assert(hud::is_copy_constructible_v<non_bitwise_type>);
205211
static_assert(hud::is_move_assignable_v<non_bitwise_type>);
@@ -253,6 +259,11 @@ namespace hud
253259
{
254260
return lhs == rhs;
255261
}
262+
263+
[[nodiscard]] constexpr bool operator()(const hud_test::non_bitwise_type &lhs, const hud::tuple<i32, i32 *> &rhs) const noexcept
264+
{
265+
return lhs == hud::get<0>(rhs);
266+
}
256267
};
257268

258269
template<>
@@ -262,6 +273,16 @@ namespace hud
262273
{
263274
return hud::hash_32<i32> {}(custom.id());
264275
}
276+
277+
[[nodiscard]] constexpr u32 operator()(const i32 id) const
278+
{
279+
return hud::hash_32<i32> {}(id);
280+
}
281+
282+
[[nodiscard]] constexpr bool operator()(const hud::tuple<i32, i32 *> &rhs) const noexcept
283+
{
284+
return hud::hash_32<i32> {}(hud::get<0>(rhs));
285+
}
265286
};
266287

267288
template<>
@@ -276,6 +297,11 @@ namespace hud
276297
{
277298
return hud::hash_64<i32> {}(id);
278299
}
300+
301+
[[nodiscard]] constexpr bool operator()(const hud::tuple<i32, i32 *> &rhs) const noexcept
302+
{
303+
return hud::hash_64<i32> {}(hud::get<0>(rhs));
304+
}
279305
};
280306

281307
template<>
@@ -285,6 +311,16 @@ namespace hud
285311
{
286312
return hud::hash_32<i32> {}(custom.id());
287313
}
314+
315+
[[nodiscard]] constexpr u32 operator()(const i32 id) const
316+
{
317+
return hud::hash_32<i32> {}(id);
318+
}
319+
320+
[[nodiscard]] constexpr bool operator()(const hud::tuple<i32, i32 *> &rhs) const noexcept
321+
{
322+
return hud::hash_32<i32> {}(hud::get<0>(rhs));
323+
}
288324
};
289325

290326
template<>
@@ -294,6 +330,16 @@ namespace hud
294330
{
295331
return hud::hash_64<i32> {}(custom.id());
296332
}
333+
334+
[[nodiscard]] constexpr u64 operator()(const i32 id) const
335+
{
336+
return hud::hash_64<i32> {}(id);
337+
}
338+
339+
[[nodiscard]] constexpr bool operator()(const hud::tuple<i32, i32 *> &rhs) const noexcept
340+
{
341+
return hud::hash_64<i32> {}(hud::get<0>(rhs));
342+
}
297343
};
298344
} // namespace hud
299345

0 commit comments

Comments
 (0)