Skip to content

Commit

Permalink
Improve hashmap and hashset
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian LALU committed Jan 23, 2025
1 parent 43ab777 commit d92b9d1
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 109 deletions.
17 changes: 10 additions & 7 deletions interface/core/containers/hashmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,20 @@ namespace hud
return add(hud::move(pair.first), hud::move(pair.second));
}
};
} // namespace hud

namespace std
{
template<typename key_t, typename value_t>
struct tuple_size<details::hashmap::slot<key_t, value_t>>
: hud::integral_constant<usize, 2>
{
};

template<std::size_t index, typename key_t, typename value_t>
struct tuple_element<index, hud::pair<key_t, value_t>>
: hud::tuple_element<index, hud::pair<key_t, value_t>>
template<usize idx_to_reach, typename key_t, typename value_t>
struct tuple_element<idx_to_reach, details::hashmap::slot<key_t, value_t>>
{
static_assert(idx_to_reach < 2, "hashmap slot index out of bounds");
using type = hud::conditional_t<idx_to_reach == 0, const typename details::hashmap::slot<key_t, value_t>::key_type, typename details::hashmap::slot<key_t, value_t>::value_type>;
};

} // namespace std
} // namespace hud

#endif // HD_INC_CORE_HASHMAP_H
105 changes: 54 additions & 51 deletions interface/core/containers/hashset.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ namespace hud
{
namespace details::hashset
{
template<typename value_t>
template<typename key_t>
struct slot
{
using key_type = value_t;
using key_type = key_t;

constexpr explicit slot(const key_type &key) noexcept
: element_(key)
Expand Down Expand Up @@ -73,7 +73,7 @@ namespace hud
return hud::forward<const slot>(s).element_;
}

value_t element_;
key_type element_;
};

template<typename key_t>
Expand Down Expand Up @@ -475,6 +475,20 @@ namespace hud
HD_ASSUME(slot_ptr_ != nullptr);
}

// constexpr iterator(const iterator<slot_type, false> &it) noexcept
// : iterator(it.control_ptr_, it.slot_ptr_)
// {
// }

/**
* Create a constant iterator from a non constant iterator.
*/
template<typename u_slot_t>
constexpr iterator(iterator<u_slot_t, false> &&it) noexcept
: iterator(hud::forward<iterator<u_slot_t, false>>(it).control_ptr_, hud::forward<iterator<u_slot_t, false>>(it).slot_ptr_)
{
}

constexpr reference_type operator*() const noexcept
{
// Ensure we are in a full control
Expand Down Expand Up @@ -551,6 +565,9 @@ namespace hud
}

private:
template<typename u_slot_t, bool u_is_const>
friend class iterator;

// The control to iterate over
control_type *control_ptr_;
// The current slot we are iterating. Keep uninitialized.
Expand Down Expand Up @@ -689,7 +706,7 @@ namespace hud

/** Find a key and return an iterator to the value. */
[[nodiscard]]
constexpr iterator find(key_type &&key) const noexcept
constexpr iterator find(const key_type &key) noexcept
{
u64 hash = hasher_type {}(key);
u64 h1 = H1(hash);
Expand Down Expand Up @@ -722,6 +739,12 @@ namespace hud
}
}

[[nodiscard]]
constexpr const_iterator find(const key_type &key) const noexcept
{
return const_cast<hashset_impl *>(this)->find(key);
}

/** Retrieves the allocator. */
[[nodiscard]] HD_FORCEINLINE constexpr const allocator_type &allocator() const noexcept
{
Expand Down Expand Up @@ -1107,61 +1130,41 @@ namespace hud
}
};

namespace details::hashset
template<typename value_t>
struct tuple_size<details::hashset::slot<value_t>>
: hud::integral_constant<usize, 1>
{
/**
* Selected when tuple_size<hashset_iterator_element_type_t>::value is ill-formed
* @tparam hashset_iterator_element_type_t The tuple-like type
*/
template<typename hashset_iterator_element_type_t, typename = void>
struct tuple_size
: hud::integral_constant<usize, 1>
{
};

/**
* Selected when tuple_size<hashset_iterator_element_type_t>::value is well-formed
* @tparam hashset_iterator_element_type_t The tuple-like type
*/
template<typename hashset_iterator_element_type_t>
struct tuple_size<hashset_iterator_element_type_t, void_t<decltype(hud::tuple_size<hashset_iterator_element_type_t>::value)>>
: hud::tuple_size<hashset_iterator_element_type_t>
{
};
};

/**
* Selected when tuple_size<hashset_iterator_element_type_t>::value is ill-formed
* @tparam hashset_iterator_element_type_t The tuple-like type
*/
template<usize index, typename hashset_iterator_element_type_t>
struct tuple_element
{
using type = hashset_iterator_element_type_t;
};
template<typename value_t>
struct tuple_size<const details::hashset::slot<value_t>>
: hud::integral_constant<usize, 1>
{
};

/**
* Selected when tuple_size<hashset_iterator_element_type_t>::value is well-formed
* @tparam hashset_iterator_element_type_t The tuple-like type
*/
template<usize index, typename f, typename s>
struct tuple_element<index, hud::pair<f, s>>
: hud::tuple_element<index, hud::pair<f, s>>
{
};
template<usize idx_to_reach, typename value_t>
struct tuple_element<idx_to_reach, details::hashset::slot<value_t>>
{
static_assert(idx_to_reach < 1, "hashset slot index out of bounds");
using type = const details::hashset::slot<value_t>::key_type;
};

} // namespace details::hashset
template<usize idx_to_reach, typename value_t>
struct tuple_element<idx_to_reach, const details::hashset::slot<value_t>>
: tuple_element<idx_to_reach, details::hashset::slot<value_t>>
{
};

template<typename slot_t, bool is_const>
struct tuple_size<hud::details::hashset::iterator<slot_t, is_const>>
: details::hashset::tuple_size<typename hud::details::hashset::iterator<slot_t, is_const>::element_type>
: tuple_size<typename hud::details::hashset::iterator<slot_t, is_const>::slot_type>
{
};

/** Specialize tuple_element for iterator that permit structured binding. */
template<usize index, typename slot_t, bool is_const>
struct tuple_element<index, hud::details::hashset::iterator<slot_t, is_const>>
: details::hashset::tuple_element<index, typename hud::details::hashset::iterator<slot_t, is_const>::element_type>

template<usize idx_to_reach, typename slot_t, bool is_const>
struct tuple_element<idx_to_reach, hud::details::hashset::iterator<slot_t, is_const>>
: tuple_element<idx_to_reach, typename hud::details::hashset::iterator<slot_t, is_const>::slot_type>
{
};

Expand All @@ -1175,9 +1178,9 @@ namespace std
{
};

template<std::size_t index, typename slot_t, bool is_const>
struct tuple_element<index, hud::details::hashset::iterator<slot_t, is_const>>
: hud::tuple_element<index, hud::details::hashset::iterator<slot_t, is_const>>
template<std::size_t idx_to_reach, typename slot_t, bool is_const>
struct tuple_element<idx_to_reach, hud::details::hashset::iterator<slot_t, is_const>>
: hud::tuple_element<idx_to_reach, hud::details::hashset::iterator<slot_t, is_const>>
{
};

Expand Down
107 changes: 56 additions & 51 deletions test/hashmap/hashmap_iterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,59 +49,64 @@ GTEST_TEST(hashmap, iterators)

GTEST_TEST(hashmap, structure_binding)
{
// // Non const Array
// {
// hud::hashmap<i32, i64> map;
// map.add({1, 11});
// map.add({2, 22});
// map.add({3, 33});
// map.add({4, 44});
// hud_assert_eq(map.count(), 4u);
// hud_assert_ge(map.max_count(), 4u);
// auto [first, second] = map.find(1);
// hud_assert_eq(first, 1);
// hud_assert_eq(second, 11);
// const auto [first_c, second_c] = map.find(1);
// hud_assert_eq(first_c, 1);
// hud_assert_eq(second_c, 11);
// }

// // Const Array
// {
// const hud::hashmap<i32, i64> map {
// {1, 11},
// {2, 22},
// {3, 33},
// {4, 44}
// };
// hud_assert_eq(map.count(), 4u);
// hud_assert_ge(map.max_count(), 4u);
// auto [first, second] = map.find(1);
// hud_assert_eq(first, 1);
// hud_assert_eq(second, 11);
// const auto [first_c, second_c] = map.find(1);
// hud_assert_eq(first_c, 1);
// hud_assert_eq(second_c, 11);
// }
hud::details::hashmap::slot<i32, u32> slot(1, 2);
auto [f, s] = slot;
s = 11;
hud_assert_eq(slot.value(), 2);
// Non const Array
{
hud::hashmap<i32, i64> map;
map.add({1, 11});
map.add({2, 22});
map.add({3, 33});
map.add({4, 44});
hud_assert_eq(map.count(), 4u);
hud_assert_ge(map.max_count(), 4u);
auto [first, second] = map.find(1);
hud_assert_eq(first, 1);
hud_assert_eq(second, 11);
const auto [first_c, second_c] = map.find(1);
hud_assert_eq(first_c, 1);
hud_assert_eq(second_c, 11);
}

// // auto is a reference
// {
// hud::hashmap<i32, i64> map;
// map.add({1, 11});
// map.add({2, 22});
// map.add({3, 33});
// map.add({4, 44});
// hud_assert_eq(map.count(), 4u);
// hud_assert_ge(map.max_count(), 4u);
// auto it = map.find(1);
// auto [first, second] = it;
// hud_assert_eq(first, 1);
// second = 111;
// hud_assert_eq(second, 111);
// auto [first_1, second_1] = map.find(1);
// hud_assert_eq(first_1, 1);
// hud_assert_eq(second_1, 111);
// }
// Const Array
{
const hud::hashmap<i32, i64> map {
{1, 11},
{2, 22},
{3, 33},
{4, 44}
};
hud_assert_eq(map.count(), 4u);
hud_assert_ge(map.max_count(), 4u);
auto [first, second] = map.find(1);
hud_assert_eq(first, 1);
hud_assert_eq(second, 11);
const auto [first_c, second_c] = map.find(1);
hud_assert_eq(first_c, 1);
hud_assert_eq(second_c, 11);
}

// auto is a reference
{
hud::hashmap<i32, i64> map;
map.add({1, 11});
map.add({2, 22});
map.add({3, 33});
map.add({4, 44});
hud_assert_eq(map.count(), 4u);
hud_assert_ge(map.max_count(), 4u);
auto it = map.find(1);
auto [first, second] = it;
hud_assert_eq(first, 1);
second = 111;
hud_assert_eq(second, 111);
auto [first_1, second_1] = map.find(1);
hud_assert_eq(first_1, 1);
hud_assert_eq(second_1, 111);
}

// // Ref do modify hash value
// {
Expand Down

0 comments on commit d92b9d1

Please sign in to comment.