Skip to content

Commit 18b42d2

Browse files
authored
Merge pull request #285 from jj683/make-set-map-nothrow-move
set/map nothrow move constructible/assignable
2 parents bd9f318 + 577b3e4 commit 18b42d2

File tree

4 files changed

+32
-11
lines changed

4 files changed

+32
-11
lines changed

immer/detail/hamts/champ.hpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -139,22 +139,26 @@ struct champ
139139

140140
static node_t* empty()
141141
{
142-
static const auto node = node_t::make_inner_n(0);
143-
return node->inc();
142+
static const auto empty_ = []{
143+
constexpr auto size = node_t::sizeof_inner_n(0);
144+
static std::aligned_storage_t<size, alignof(std::max_align_t)> storage;
145+
return node_t::make_inner_n_into(&storage, size, 0u);
146+
}();
147+
return empty_->inc();
144148
}
145149

146-
champ(node_t* r, size_t sz = 0)
150+
champ(node_t* r, size_t sz = 0) noexcept
147151
: root{r}
148152
, size{sz}
149153
{}
150154

151-
champ(const champ& other)
155+
champ(const champ& other) noexcept
152156
: champ{other.root, other.size}
153157
{
154158
inc();
155159
}
156160

157-
champ(champ&& other)
161+
champ(champ&& other) noexcept
158162
: champ{empty()}
159163
{
160164
swap(*this, other);
@@ -167,13 +171,13 @@ struct champ
167171
return *this;
168172
}
169173

170-
champ& operator=(champ&& other)
174+
champ& operator=(champ&& other) noexcept
171175
{
172176
swap(*this, other);
173177
return *this;
174178
}
175179

176-
friend void swap(champ& x, champ& y)
180+
friend void swap(champ& x, champ& y) noexcept
177181
{
178182
using std::swap;
179183
swap(x.root, y.root);

immer/detail/hamts/node.hpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,11 @@ struct node
222222
return can_mutate(impl.d.data.inner.values, e);
223223
}
224224

225-
static node_t* make_inner_n(count_t n)
225+
static node_t* make_inner_n_into(void* buffer, std::size_t size, count_t n)
226226
{
227227
assert(n <= branches<B>);
228-
auto m = heap::allocate(sizeof_inner_n(n));
229-
auto p = new (m) node_t;
230-
assert(p == (node_t*) m);
228+
assert(size >= sizeof_inner_n(n));
229+
auto p = new (buffer) node_t;
231230
#if IMMER_TAGGED_NODE
232231
p->impl.d.kind = node_t::kind_t::inner;
233232
#endif
@@ -237,6 +236,13 @@ struct node
237236
return p;
238237
}
239238

239+
static node_t* make_inner_n(count_t n)
240+
{
241+
assert(n <= branches<B>);
242+
auto m = heap::allocate(sizeof_inner_n(n));
243+
return make_inner_n_into(m, sizeof_inner_n(n), n);
244+
}
245+
240246
static node_t* make_inner_n(count_t n, values_t* values)
241247
{
242248
auto p = make_inner_n(n);

immer/map.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -547,4 +547,9 @@ class map
547547
impl_t impl_ = impl_t::empty();
548548
};
549549

550+
static_assert(std::is_nothrow_move_constructible<map<int, int>>::value,
551+
"map is not nothrow move constructible");
552+
static_assert(std::is_nothrow_move_assignable<map<int, int>>::value,
553+
"map is not nothrow move assignable");
554+
550555
} // namespace immer

immer/set.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,10 @@ class set
292292
impl_t impl_ = impl_t::empty();
293293
};
294294

295+
static_assert(std::is_nothrow_move_constructible<set<int>>::value,
296+
"set is not nothrow move constructible");
297+
static_assert(std::is_nothrow_move_assignable<set<int>>::value,
298+
"set is not nothrow move assignable");
299+
300+
295301
} // namespace immer

0 commit comments

Comments
 (0)