Skip to content

Commit ee33df0

Browse files
author
Julian LALU
committed
Improve hashmap and hashset
1 parent 8956da1 commit ee33df0

File tree

5 files changed

+276
-144
lines changed

5 files changed

+276
-144
lines changed

interface/core/containers/hashmap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ namespace hud
6363
}
6464

6565
template<usize idx_to_reach>
66-
[[nodiscard]] friend constexpr auto get(slot &&s) noexcept
66+
[[nodiscard]] friend constexpr decltype(auto) get(slot &&s) noexcept
6767
{
6868
return hud::get<idx_to_reach>(hud::forward<slot>(s).element_);
6969
}
7070

7171
template<usize idx_to_reach>
72-
[[nodiscard]] friend constexpr auto get(const slot &&s) noexcept
72+
[[nodiscard]] friend constexpr decltype(auto) get(const slot &&s) noexcept
7373
{
7474
return hud::get<idx_to_reach>(hud::forward<const slot>(s).element_);
7575
}

interface/core/containers/hashset.h

Lines changed: 36 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -34,43 +34,43 @@ namespace hud
3434
{
3535
}
3636

37-
[[nodiscard]] constexpr const key_type &get_key() const noexcept
37+
[[nodiscard]] constexpr const key_type &key() const noexcept
3838
{
3939
return element_;
4040
}
4141

4242
template<typename slot_t>
43-
[[nodiscard]] static constexpr decltype(auto) get_key(slot_t &&s) noexcept
43+
[[nodiscard]] static constexpr decltype(auto) key(slot_t &&s) noexcept
4444
{
4545
return hud::forward<slot_t>(s).element_;
4646
}
4747

4848
template<usize idx_to_reach>
4949
[[nodiscard]] friend constexpr decltype(auto) get(slot &s) noexcept
5050
{
51-
static_assert(idx_to_reach != 0, "Index out of bound");
51+
static_assert(idx_to_reach == 0, "Index out of bound");
5252
return s.element_;
5353
}
5454

5555
template<usize idx_to_reach>
5656
[[nodiscard]] friend constexpr decltype(auto) get(const slot &s) noexcept
5757
{
58-
static_assert(idx_to_reach != 0, "Index out of bound");
58+
static_assert(idx_to_reach == 0, "Index out of bound");
5959
return s.element_;
6060
}
6161

6262
template<usize idx_to_reach>
6363
[[nodiscard]] friend constexpr decltype(auto) get(slot &&s) noexcept
6464
{
65-
static_assert(idx_to_reach != 0, "Index out of bound");
66-
return hud::forward<slot>(s).element_;
65+
static_assert(idx_to_reach == 0, "Index out of bound");
66+
return hud::forward<key_type>(hud::forward<slot>(s).element_);
6767
}
6868

6969
template<usize idx_to_reach>
7070
[[nodiscard]] friend constexpr decltype(auto) get(const slot &&s) noexcept
7171
{
72-
static_assert(idx_to_reach != 0, "Index out of bound");
73-
return hud::forward<const slot>(s).element_;
72+
static_assert(idx_to_reach == 0, "Index out of bound");
73+
return hud::forward<const key_type>(hud::forward<const slot>(s).element_);
7474
}
7575

7676
key_type element_;
@@ -451,9 +451,6 @@ namespace hud
451451
{
452452
public:
453453
using slot_type = hud::conditional_t<is_const, const slot_t, slot_t>;
454-
// using element_type = hud::conditional_t<is_const, const typename slot_type::element_type, typename slot_type::element_type>;
455-
using key_type = hud::conditional_t<is_const, const typename slot_t::key_type, typename slot_t::key_type>;
456-
using value_type = hud::conditional_t<is_const, const typename slot_t::value_type, typename slot_t::value_type>;
457454
using pointer_type = hud::add_pointer_t<slot_type>;
458455
using reference_type = hud::add_lvalue_reference_t<slot_type>;
459456

@@ -528,37 +525,6 @@ namespace hud
528525
return control_ptr_ != other.control_ptr_;
529526
}
530527

531-
template<typename iterator_t>
532-
[[nodiscard]] static constexpr decltype(auto) get_key(iterator_t &&s) noexcept
533-
{
534-
return slot_t::get_key(*(hud::forward<iterator_t>(s).slot_ptr_));
535-
}
536-
537-
private:
538-
template<usize idx_to_reach>
539-
[[nodiscard]] friend constexpr decltype(auto) get(iterator &s) noexcept
540-
{
541-
return get<idx_to_reach>(*(s.slot_ptr_));
542-
}
543-
544-
template<usize idx_to_reach>
545-
[[nodiscard]] friend constexpr decltype(auto) get(const iterator &s) noexcept
546-
{
547-
return get<idx_to_reach>(*(s.slot_ptr_));
548-
}
549-
550-
template<usize idx_to_reach>
551-
[[nodiscard]] friend constexpr auto get(iterator &&s) noexcept
552-
{
553-
return get<idx_to_reach>(*(hud::forward<iterator>(s).slot_ptr_));
554-
}
555-
556-
template<usize idx_to_reach>
557-
[[nodiscard]] friend constexpr auto get(const iterator &&s) noexcept
558-
{
559-
return get<idx_to_reach>(*(hud::forward<const iterator>(s).slot_ptr_));
560-
}
561-
562528
private:
563529
template<typename u_slot_t, bool u_is_const>
564530
friend class iterator;
@@ -661,6 +627,25 @@ namespace hud
661627
}
662628
}
663629

630+
/**
631+
* Insert a key in the hashset.
632+
* @param key The key associated with the `value`
633+
* @param args List of arguments pass to `value_type` constructor after the `key` itself
634+
* @return Iterator to the `value`
635+
*/
636+
template<typename... args_t>
637+
requires(hud::is_constructible_v<slot_type, args_t...>)
638+
constexpr iterator add(args_t &&...args) noexcept
639+
{
640+
hud::pair<usize, bool> res = find_or_insert_no_construct(key);
641+
slot_type *slot_ptr = slot_ptr_ + res.first;
642+
if (res.second)
643+
{
644+
hud::memory::construct_at(slot_ptr, hud::move(key), hud::forward<args_t>(args)...);
645+
}
646+
return {control_ptr_ + res.first, slot_ptr};
647+
}
648+
664649
/**
665650
* Insert a key in the hashset.
666651
* @param key The key associated with the `value`
@@ -716,7 +701,7 @@ namespace hud
716701
{
717702
usize slot_index_that_match_h2 = slot_index + group_index_that_match_h2 & max_slot_count_;
718703
slot_type *slot_that_match_h2 = slot_ptr_ + slot_index_that_match_h2;
719-
if (key_equal_t {}(slot_t::get_key(*slot_that_match_h2), key)) [[likely]]
704+
if (key_equal_t {}(slot_that_match_h2->key(), key)) [[likely]]
720705
{
721706
return {control_ptr_ + slot_index_that_match_h2, slot_that_match_h2};
722707
}
@@ -820,7 +805,7 @@ namespace hud
820805
{
821806
usize slot_index_that_match_h2 = slot_index + group_index_that_match_h2 & max_slot_count_;
822807
slot_type *slot_that_match_h2 = slot_ptr_ + slot_index_that_match_h2;
823-
if (key_equal_t {}(slot_t::get_key(*slot_that_match_h2), key)) [[likely]]
808+
if (key_equal_t {}(slot_that_match_h2->key(), key)) [[likely]]
824809
{
825810
return {slot_index_that_match_h2, false};
826811
}
@@ -899,12 +884,12 @@ namespace hud
899884
++it)
900885
{
901886
// Compute the hash
902-
u64 hash = hasher_type {}(iterator::get_key(it));
887+
u64 hash = hasher_type {}(it->key());
903888
// Find H1 slot index
904889
u64 h1 = H1(hash);
905890
usize slot_index = find_first_empty_or_deleted(control_ptr_, old_max_slot_count, h1);
906891
// Save h2 in control h1 index
907-
control::set_h2(control_ptr_, slot_index, H2(hash), old_max_slot_count);
892+
control::set_h2(control_ptr_, slot_index, H2(hash), max_slot_count_);
908893
// Move old slot to new slot
909894
hud::memory::move_or_copy_construct_then_destroy(slot_ptr_ + slot_index, hud::move(*it));
910895
}
@@ -1125,42 +1110,17 @@ namespace hud
11251110
}
11261111
};
11271112

1128-
template<typename value_t>
1129-
struct tuple_size<details::hashset::slot<value_t>>
1130-
: hud::integral_constant<usize, 1>
1131-
{
1132-
};
1133-
1134-
template<typename value_t>
1135-
struct tuple_size<const details::hashset::slot<value_t>>
1113+
template<typename key_t>
1114+
struct tuple_size<details::hashset::slot<key_t>>
11361115
: hud::integral_constant<usize, 1>
11371116
{
11381117
};
11391118

1140-
template<usize idx_to_reach, typename value_t>
1141-
struct tuple_element<idx_to_reach, details::hashset::slot<value_t>>
1119+
template<usize idx_to_reach, typename key_t>
1120+
struct tuple_element<idx_to_reach, details::hashset::slot<key_t>>
11421121
{
11431122
static_assert(idx_to_reach < 1, "hashset slot index out of bounds");
1144-
using type = typename const details::hashset::slot<value_t>::key_type;
1145-
};
1146-
1147-
template<usize idx_to_reach, typename value_t>
1148-
struct tuple_element<idx_to_reach, const details::hashset::slot<value_t>>
1149-
: tuple_element<idx_to_reach, details::hashset::slot<value_t>>
1150-
{
1151-
};
1152-
1153-
template<typename slot_t, bool is_const>
1154-
struct tuple_size<hud::details::hashset::iterator<slot_t, is_const>>
1155-
: tuple_size<typename hud::details::hashset::iterator<slot_t, is_const>::slot_type>
1156-
{
1157-
};
1158-
1159-
/** Specialize tuple_element for iterator that permit structured binding. */
1160-
template<usize idx_to_reach, typename slot_t, bool is_const>
1161-
struct tuple_element<idx_to_reach, hud::details::hashset::iterator<slot_t, is_const>>
1162-
: tuple_element<idx_to_reach, typename hud::details::hashset::iterator<slot_t, is_const>::slot_type>
1163-
{
1123+
using type = const typename details::hashset::slot<key_t>::key_type;
11641124
};
11651125

11661126
} // namespace hud
@@ -1179,17 +1139,5 @@ namespace std
11791139
{
11801140
};
11811141

1182-
template<typename slot_t, bool is_const>
1183-
struct tuple_size<hud::details::hashset::iterator<slot_t, is_const>>
1184-
: hud::tuple_size<hud::details::hashset::iterator<slot_t, is_const>>
1185-
{
1186-
};
1187-
1188-
template<std::size_t idx_to_reach, typename slot_t, bool is_const>
1189-
struct tuple_element<idx_to_reach, hud::details::hashset::iterator<slot_t, is_const>>
1190-
: hud::tuple_element<idx_to_reach, hud::details::hashset::iterator<slot_t, is_const>>
1191-
{
1192-
};
1193-
11941142
} // namespace std
11951143
#endif // HD_INC_CORE_HASHSET_H

test/hashmap/hashmap_iterator.cpp

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ GTEST_TEST(hashmap, structure_binding)
5858
map.add({4, 44});
5959
hud_assert_eq(map.count(), 4u);
6060
hud_assert_ge(map.max_count(), 4u);
61-
auto [first, second] = map.find(1);
61+
auto [first, second] = *map.find(1);
6262
hud_assert_eq(first, 1);
6363
hud_assert_eq(second, 11);
64-
const auto [first_c, second_c] = map.find(1);
64+
const auto [first_c, second_c] = *map.find(1);
6565
hud_assert_eq(first_c, 1);
6666
hud_assert_eq(second_c, 11);
6767
}
@@ -76,10 +76,10 @@ GTEST_TEST(hashmap, structure_binding)
7676
};
7777
hud_assert_eq(map.count(), 4u);
7878
hud_assert_ge(map.max_count(), 4u);
79-
auto [first, second] = map.find(1);
79+
auto [first, second] = *map.find(1);
8080
hud_assert_eq(first, 1);
8181
hud_assert_eq(second, 11);
82-
const auto [first_c, second_c] = map.find(1);
82+
const auto [first_c, second_c] = *map.find(1);
8383
hud_assert_eq(first_c, 1);
8484
hud_assert_eq(second_c, 11);
8585
}
@@ -93,14 +93,14 @@ GTEST_TEST(hashmap, structure_binding)
9393
map.add({4, 44});
9494
hud_assert_eq(map.count(), 4u);
9595
hud_assert_ge(map.max_count(), 4u);
96-
auto it = map.find(1);
97-
auto [first, second] = it;
98-
hud_assert_eq(first, 1);
99-
second = 111;
100-
hud_assert_eq(second, 111);
101-
auto [first_1, second_1] = map.find(1);
102-
hud_assert_eq(first_1, 1);
103-
hud_assert_eq(second_1, 11);
96+
auto [first, second] = *map.find(4);
97+
hud_assert_eq(first, 4);
98+
second = 444;
99+
hud_assert_eq(first, 4);
100+
hud_assert_eq(second, 444);
101+
auto [first_1, second_1] = *map.find(4);
102+
hud_assert_eq(first_1, 4);
103+
hud_assert_eq(second_1, 44);
104104
}
105105

106106
// auto& is a reference
@@ -112,14 +112,13 @@ GTEST_TEST(hashmap, structure_binding)
112112
map.add({4, 44});
113113
hud_assert_eq(map.count(), 4u);
114114
hud_assert_ge(map.max_count(), 4u);
115-
auto it = map.find(1);
116-
auto &[first, second] = it;
117-
hud_assert_eq(first, 1);
118-
second = 111;
119-
hud_assert_eq(second, 111);
120-
auto [first_1, second_1] = map.find(1);
121-
hud_assert_eq(first_1, 1);
122-
hud_assert_eq(second_1, 111);
115+
auto &[first, second] = *map.find(4);
116+
hud_assert_eq(first, 4);
117+
second = 444;
118+
hud_assert_eq(second, 444);
119+
auto &[first_1, second_1] = *map.find(4);
120+
hud_assert_eq(first_1, 4);
121+
hud_assert_eq(second_1, 444);
123122
}
124123

125124
// auto&& is a reference
@@ -131,12 +130,11 @@ GTEST_TEST(hashmap, structure_binding)
131130
map.add({4, 44});
132131
hud_assert_eq(map.count(), 4u);
133132
hud_assert_ge(map.max_count(), 4u);
134-
auto it = map.find(1);
135-
auto &[first, second] = it;
133+
auto &&[first, second] = *map.find(1);
136134
hud_assert_eq(first, 1);
137135
second = 111;
138136
hud_assert_eq(second, 111);
139-
auto [first_1, second_1] = map.find(1);
137+
auto &&[first_1, second_1] = *map.find(1);
140138
hud_assert_eq(first_1, 1);
141139
hud_assert_eq(second_1, 111);
142140
}

0 commit comments

Comments
 (0)