Skip to content

Commit a6aa8d1

Browse files
committed
Improve HashMap
1 parent 73ac56c commit a6aa8d1

File tree

3 files changed

+40
-12
lines changed

3 files changed

+40
-12
lines changed

interface/core/containers/hashmap.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,22 @@ namespace hud
357357
}
358358

359359
/**
360-
* Insert a key and value in the hashmap by piecewise construct them in place.
361-
* If the `key_type` is not hashable with the `key_tuple_t` a temporary key is created to find it in the hashmap
362-
* To make the `key_type` hashable with the `key_tuple_t` you must specialize the `hud::equal<key_type>` functor by adding the function
363-
* `[[nodiscard]] constexpr bool operator()(const hud::tuple<...&&> &rhs) const noexcept` or by
360+
* Adds a new element to the container using piecewise construction of the key and value.
361+
*
362+
* If an element with the given key already exists, returns an iterator to it.
363+
* Otherwise, constructs a new element in-place using the provided key and value tuples.
364+
*
365+
* The key can be provided either as a fully constructed `key_type` or as a tuple of arguments
366+
* used to construct the key in-place. If the key tuple can't be used directly (e.g., it's not
367+
* hashable or comparable), it must be convertible into a valid `key_type`.
368+
*
369+
* To enable custom key lookup using a tuple of arguments, you can specialize the `hud::equal<key_type>`
370+
* and `hud::hash<key_type>` functors to support comparisons and hashes against a forwarding tuple
371+
* (i.e., `hud::tuple<Args&&...>&&`).
372+
*
373+
* @param key_tuple Tuple of arguments used to identify or construct the key.
374+
* @param value_tuple Tuple of arguments used to construct the associated value.
375+
* @return An iterator to the existing or newly inserted element.
364376
*/
365377
template<typename key_tuple_t, typename value_tuple_t>
366378
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple) noexcept

interface/core/containers/hashset.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,17 +1159,30 @@ namespace hud
11591159
}
11601160

11611161
/**
1162-
* Finds or inserts a slot corresponding to the given key.
1163-
* If the key is not found, a new slot is created by constructing it with the key followed by `args`.
1164-
* If the `key_type` is not hashable with the `key_tuple_t` a temporary key is created to find it in the hashmap
1165-
* To make the `key_type` hashable with the `key_tuple_t` you must specialize the `hud::equal<key_type>` functor by adding the function
1166-
* @param key The key used to find or insert the slot.
1167-
* @param args The arguments forwarded to the `slot_type` constructor after the key.
1168-
* @return An iterator to the inserted or existing value.
1162+
* Adds a new element to the container using piecewise construction of the key and value.
1163+
*
1164+
* If an element with the given key already exists, returns an iterator to it.
1165+
* Otherwise, constructs a new element in-place using the provided key and value tuples.
1166+
*
1167+
* The key can be provided either as a fully constructed `key_type` or as a tuple of arguments
1168+
* used to construct the key in-place. If the key tuple can't be used directly (e.g., it's not
1169+
* hashable or comparable), it must be convertible into a valid `key_type`.
1170+
*
1171+
* To enable custom key lookup using a tuple of arguments, you can specialize the `hud::equal<key_type>`
1172+
* and `hud::hash<key_type>` functors to support comparisons and hashes against a forwarding tuple
1173+
* (i.e., `hud::tuple<Args&&...>&&`).
1174+
*
1175+
* @param key_tuple Tuple of arguments used to identify or construct the key.
1176+
* @param value_tuple Tuple of arguments used to construct the associated value.
1177+
* @return An iterator to the existing or newly inserted element.
11691178
*/
11701179
template<typename key_tuple_t, typename value_tuple_t>
11711180
constexpr iterator add(hud::tag_piecewise_construct_t, key_tuple_t &&key_tuple, value_tuple_t &&value_tuple) noexcept
11721181
{
1182+
/**
1183+
* If the tuple can't be used directly as a hashable/comparable key,
1184+
* we unpack its elements and construct a key_type from them.
1185+
*/
11731186
constexpr auto forward_key = []<usize... indices_key>(
11741187
key_tuple_t &&key_tuple,
11751188
hud::index_sequence<indices_key...>
@@ -1181,6 +1194,8 @@ namespace hud
11811194
}
11821195
else
11831196
{
1197+
static_assert(hud::is_constructible_v<key_type, decltype(hud::get<indices_key>(key_tuple))...>, "key_type is neither hashable nor comparable with the given tuple, and cannot be constructed from its values. "
1198+
"Ensure that hud::equal and hud::hash support hud::tuple<...&&>&&, or provide a constructor for key_type that accepts the tuple elements.");
11841199
return key_type(hud::get<indices_key>(key_tuple)...);
11851200
}
11861201
};

test/hashmap/hashmap_add.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5060,6 +5060,7 @@ GTEST_TEST(hashmap, add_by_piecewise_construct_non_bitwise_same_type)
50605060
using value_type = hud_test::non_bitwise_type;
50615061
using hashmap_type = hud::hashmap<key_type, value_type, hud::hash_64<key_type>, hud::equal<key_type>, hud_test::allocator_watcher<1>>;
50625062

5063+
static_assert(hud::is_hashable_64_v<key_type, decltype(hud::forward_as_tuple(1, (i32 *)nullptr))>);
50635064
static_assert(hud::is_hashable_64_v<key_type, decltype(hud::forward_as_tuple(1, (i32 *)nullptr))>);
50645065
static_assert(hud::is_comparable_with_equal_v<key_type, decltype(hud::forward_as_tuple(1, (i32 *)nullptr))>);
50655066
const auto test = []()
@@ -5069,7 +5070,7 @@ GTEST_TEST(hashmap, add_by_piecewise_construct_non_bitwise_same_type)
50695070
hashmap_type map;
50705071
map.reserve(reserved_size);
50715072

5072-
const auto it = map.add(hud::tag_piecewise_construct, hud::forward_as_tuple(1, ptr + 0), hud::forward_as_tuple(2, ptr + 1));
5073+
const auto it = map.add(hud::tag_piecewise_construct, hud::forward_as_tuple(1, ptr), hud::forward_as_tuple(2, ptr + 1));
50735074

50745075
return std::tuple {
50755076
map.count() == 1, // 0

0 commit comments

Comments
 (0)