Skip to content

Commit 7a378bf

Browse files
author
Julian LALU
committed
Separate slot and slot_storage to disable the possibilty for the user to move a slot
1 parent cbb6e08 commit 7a378bf

File tree

6 files changed

+563
-419
lines changed

6 files changed

+563
-419
lines changed

interface/core/containers/hashmap.h

Lines changed: 99 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,12 @@ namespace hud
77
namespace details::hashmap
88
{
99
template<typename key_t, typename value_t>
10-
struct slot
10+
class slot_storage
1111
{
12+
public:
1213
using key_type = key_t;
1314
using value_type = value_t;
1415

15-
template<typename u_key_t, typename u_value_t>
16-
requires(hud::is_constructible_v<hud::pair<key_type, value_type>, u_key_t, u_value_t>)
17-
constexpr explicit slot(const u_key_t &key, const u_value_t &value) noexcept
18-
: element_(key, value)
19-
{
20-
}
21-
22-
template<typename u_key_t, typename u_value_t>
23-
requires(hud::is_constructible_v<hud::pair<key_type, value_type>, u_key_t, u_value_t>)
24-
constexpr explicit slot(u_key_t &&key, u_value_t &&value) noexcept
25-
: element_(hud::forward<u_key_t>(key), hud::forward<u_value_t>(value))
26-
{
27-
}
28-
29-
constexpr explicit(!(hud::is_convertible_v<const hud::pair<key_type, value_type> &, hud::pair<key_type, value_type>>)) slot(const slot &other) noexcept
30-
requires(hud::is_nothrow_copy_constructible_v<hud::pair<key_type, value_type>>)
31-
= default;
32-
33-
template<typename u_key_t = key_t, typename u_value_t = value_t>
34-
requires(hud::is_copy_constructible_v<hud::pair<key_type, value_type>, hud::pair<u_key_t, u_value_t>>)
35-
constexpr explicit(!(hud::is_convertible_v<const hud::pair<key_type, value_type> &, hud::pair<u_key_t, u_value_t>>)) slot(const slot<u_key_t, u_value_t> &other) noexcept
36-
: element_(other.element_)
37-
{
38-
static_assert(hud::is_nothrow_copy_constructible_v<key_t, u_key_t>, "key_t(const u_key_t&) copy constructor is throwable. slot is not designed to allow throwable copy constructible components");
39-
static_assert(hud::is_nothrow_copy_constructible_v<value_t, u_value_t>, "value_t(const u_value_t&) copy constructor is throwable. slot is not designed to allow throwable copy constructible components");
40-
}
41-
42-
constexpr explicit(!(hud::is_convertible_v<hud::pair<key_type, value_type>, hud::pair<key_type, value_type>>)) slot(slot &&other) noexcept
43-
requires(hud::is_nothrow_move_constructible_v<hud::pair<key_type, value_type>>)
44-
= default;
45-
46-
template<typename u_key_t = key_t, typename u_value_t = value_t>
47-
requires(hud::is_move_constructible_v<hud::pair<key_type, value_type>, hud::pair<u_key_t, u_value_t>>)
48-
constexpr explicit(!(hud::is_convertible_v<hud::pair<key_type, value_type>, hud::pair<key_type, value_type>>)) slot(slot<u_key_t, u_value_t> &&other) noexcept
49-
: element_(hud::move(other.element_))
50-
{
51-
static_assert(hud::is_nothrow_copy_constructible_v<key_t, u_key_t>, "key_t(const u_key_t&) copy constructor is throwable. slot is not designed to allow throwable copy constructible components");
52-
static_assert(hud::is_nothrow_copy_constructible_v<value_t, u_value_t>, "value_t(const u_value_t&) copy constructor is throwable. slot is not designed to allow throwable copy constructible components");
53-
}
54-
5516
[[nodiscard]] constexpr const key_type &key() noexcept
5617
{
5718
return hud::get<0>(element_);
@@ -73,39 +34,118 @@ namespace hud
7334
}
7435

7536
template<usize idx_to_reach>
76-
[[nodiscard]] friend constexpr decltype(auto) get(slot &s) noexcept
37+
[[nodiscard]] friend constexpr decltype(auto) get(slot_storage &s) noexcept
7738
{
7839
return hud::get<idx_to_reach>(s.element_);
7940
}
8041

8142
template<usize idx_to_reach>
82-
[[nodiscard]] friend constexpr decltype(auto) get(const slot &s) noexcept
43+
[[nodiscard]] friend constexpr decltype(auto) get(const slot_storage &s) noexcept
8344
{
8445
return hud::get<idx_to_reach>(s.element_);
8546
}
8647

8748
template<usize idx_to_reach>
88-
[[nodiscard]] friend constexpr decltype(auto) get(slot &&s) noexcept
49+
[[nodiscard]] friend constexpr decltype(auto) get(slot_storage &&s) noexcept
8950
{
90-
return hud::get<idx_to_reach>(hud::forward<slot>(s).element_);
51+
return hud::get<idx_to_reach>(hud::forward<slot_storage>(s).element_);
9152
}
9253

9354
template<usize idx_to_reach>
94-
[[nodiscard]] friend constexpr decltype(auto) get(const slot &&s) noexcept
55+
[[nodiscard]] friend constexpr decltype(auto) get(const slot_storage &&s) noexcept
9556
{
96-
return hud::get<idx_to_reach>(hud::forward<const slot>(s).element_);
57+
return hud::get<idx_to_reach>(hud::forward<const slot_storage>(s).element_);
9758
}
9859

9960
private:
10061
template<typename u_key_t, typename u_value_t>
101-
friend struct slot;
62+
friend class slot_storage;
10263

103-
private:
64+
protected:
65+
template<typename u_key_t, typename u_value_t>
66+
requires(hud::is_constructible_v<hud::pair<key_type, value_type>, u_key_t, u_value_t>)
67+
constexpr explicit slot_storage(const u_key_t &key, const u_value_t &value) noexcept
68+
: element_(key, value)
69+
{
70+
}
71+
72+
template<typename u_key_t, typename u_value_t>
73+
requires(hud::is_constructible_v<hud::pair<key_type, value_type>, u_key_t, u_value_t>)
74+
constexpr explicit slot_storage(u_key_t &&key, u_value_t &&value) noexcept
75+
: element_(hud::forward<u_key_t>(key), hud::forward<u_value_t>(value))
76+
{
77+
}
78+
79+
template<typename u_key_t = key_t, typename u_value_t = value_t>
80+
requires(hud::is_copy_constructible_v<hud::pair<key_type, value_type>, hud::pair<u_key_t, u_value_t>>)
81+
constexpr explicit(!(hud::is_convertible_v<const hud::pair<key_type, value_type> &, hud::pair<u_key_t, u_value_t>>)) slot_storage(const slot_storage<u_key_t, u_value_t> &other) noexcept
82+
: element_(other.element_)
83+
{
84+
static_assert(hud::is_nothrow_copy_constructible_v<key_t, u_key_t>, "key_t(const u_key_t&) copy constructor is throwable. slot_storage is not designed to allow throwable copy constructible components");
85+
static_assert(hud::is_nothrow_copy_constructible_v<value_t, u_value_t>, "value_t(const u_value_t&) copy constructor is throwable. slot_storage is not designed to allow throwable copy constructible components");
86+
}
87+
88+
template<typename u_key_t = key_t, typename u_value_t = value_t>
89+
requires(hud::is_move_constructible_v<hud::pair<key_type, value_type>, hud::pair<u_key_t, u_value_t>>)
90+
constexpr explicit(!(hud::is_convertible_v<hud::pair<key_type, value_type>, hud::pair<key_type, value_type>>)) slot_storage(slot_storage<u_key_t, u_value_t> &&other) noexcept
91+
: element_(hud::move(other.element_))
92+
{
93+
static_assert(hud::is_nothrow_copy_constructible_v<key_t, u_key_t>, "key_t(const u_key_t&) copy constructor is throwable. slot_storage is not designed to allow throwable copy constructible components");
94+
static_assert(hud::is_nothrow_copy_constructible_v<value_t, u_value_t>, "value_t(const u_value_t&) copy constructor is throwable. slot_storage is not designed to allow throwable copy constructible components");
95+
}
96+
97+
protected:
10498
hud::pair<key_type, value_type> element_;
10599
};
106100

107-
template<typename key_t>
108-
struct default_hasher
101+
template<typename key_t, typename value_t>
102+
struct slot
103+
: slot_storage<key_t, value_t>
104+
{
105+
106+
using storage = slot_storage<key_t, value_t>;
107+
using key_type = storage::key_type;
108+
using value_type = storage::value_type;
109+
110+
template<typename u_key_t, typename u_value_t>
111+
requires(hud::is_constructible_v<hud::pair<key_type, value_type>, u_key_t, u_value_t>)
112+
constexpr explicit slot(const u_key_t &key, const u_value_t &value) noexcept
113+
: storage(key, value)
114+
{
115+
}
116+
117+
template<typename u_key_t, typename u_value_t>
118+
requires(hud::is_constructible_v<hud::pair<key_type, value_type>, u_key_t, u_value_t>)
119+
constexpr explicit slot(u_key_t &&key, u_value_t &&value) noexcept
120+
: storage(hud::forward<u_key_t>(key), hud::forward<u_value_t>(value))
121+
{
122+
}
123+
124+
constexpr explicit(!(hud::is_convertible_v<const hud::pair<key_type, value_type> &, hud::pair<key_type, value_type>>)) slot(const slot &other) noexcept
125+
requires(hud::is_nothrow_copy_constructible_v<hud::pair<key_type, value_type>>)
126+
= default;
127+
128+
template<typename u_key_t = key_t, typename u_value_t = value_t>
129+
requires(hud::is_copy_constructible_v<hud::pair<key_type, value_type>, hud::pair<u_key_t, u_value_t>>)
130+
constexpr explicit(!(hud::is_convertible_v<const hud::pair<key_type, value_type> &, hud::pair<u_key_t, u_value_t>>)) slot(const slot<u_key_t, u_value_t> &other) noexcept
131+
: storage(other)
132+
{
133+
}
134+
135+
constexpr explicit(!(hud::is_convertible_v<hud::pair<key_type, value_type>, hud::pair<key_type, value_type>>)) slot(slot &&other) noexcept
136+
requires(hud::is_nothrow_move_constructible_v<hud::pair<key_type, value_type>>)
137+
= default;
138+
139+
template<typename u_key_t = key_t, typename u_value_t = value_t>
140+
requires(hud::is_move_constructible_v<hud::pair<key_type, value_type>, hud::pair<u_key_t, u_value_t>>)
141+
constexpr explicit(!(hud::is_convertible_v<hud::pair<key_type, value_type>, hud::pair<key_type, value_type>>)) slot(slot<u_key_t, u_value_t> &&other) noexcept
142+
: storage(hud::move(other))
143+
{
144+
}
145+
};
146+
147+
template<typename key_t> struct default_hasher
148+
109149
{
110150
/** Hash the value and combine the value with the current hasher value. */
111151
template<typename... type_t>
@@ -219,31 +259,31 @@ namespace hud
219259
};
220260

221261
template<typename key_t, typename value_t>
222-
struct tuple_size<details::hashmap::slot<key_t, value_t>>
262+
struct tuple_size<details::hashmap::slot_storage<key_t, value_t>>
223263
: hud::integral_constant<usize, 2>
224264
{
225265
};
226266

227267
template<usize idx_to_reach, typename key_t, typename value_t>
228-
struct tuple_element<idx_to_reach, details::hashmap::slot<key_t, value_t>>
268+
struct tuple_element<idx_to_reach, details::hashmap::slot_storage<key_t, value_t>>
229269
{
230-
static_assert(idx_to_reach < 2, "hashmap slot index out of bounds");
231-
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>;
270+
static_assert(idx_to_reach < 2, "hashmap slot_storage index out of bounds");
271+
using type = hud::conditional_t<idx_to_reach == 0, const typename details::hashmap::slot_storage<key_t, value_t>::key_type, typename details::hashmap::slot_storage<key_t, value_t>::value_type>;
232272
};
233273

234274
} // namespace hud
235275

236276
namespace std
237277
{
238278
template<typename key_t, typename value_t>
239-
struct tuple_size<hud::details::hashmap::slot<key_t, value_t>>
240-
: hud::tuple_size<hud::details::hashmap::slot<key_t, value_t>>
279+
struct tuple_size<hud::details::hashmap::slot_storage<key_t, value_t>>
280+
: hud::tuple_size<hud::details::hashmap::slot_storage<key_t, value_t>>
241281
{
242282
};
243283

244284
template<std::size_t idx_to_reach, typename key_t, typename value_t>
245-
struct tuple_element<idx_to_reach, hud::details::hashmap::slot<key_t, value_t>>
246-
: hud::tuple_element<idx_to_reach, hud::details::hashmap::slot<key_t, value_t>>
285+
struct tuple_element<idx_to_reach, hud::details::hashmap::slot_storage<key_t, value_t>>
286+
: hud::tuple_element<idx_to_reach, hud::details::hashmap::slot_storage<key_t, value_t>>
247287
{
248288
};
249289
} // namespace std

0 commit comments

Comments
 (0)