Skip to content

Commit 94bbd0b

Browse files
committed
Make range types trivially relocatable
1 parent 02bdb12 commit 94bbd0b

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

subspace/ops/range.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "subspace/iter/__private/step.h"
1818
#include "subspace/iter/iterator_defn.h"
1919
#include "subspace/mem/move.h"
20+
#include "subspace/mem/relocate.h"
2021
#include "subspace/ops/ord.h"
2122
#include "subspace/option/option.h"
2223

@@ -65,10 +66,9 @@ class RangeIter<Final, T, true> : public ::sus::iter::IteratorImpl<Final, T> {
6566

6667
// sus::iter::Iterator trait optional method.
6768
::sus::iter::SizeHint size_hint() const noexcept final {
68-
Option<::sus::num::usize> steps =
69-
::sus::iter::__private::steps_between(
70-
static_cast<const Final*>(this)->start,
71-
static_cast<const Final*>(this)->finish);
69+
Option<::sus::num::usize> steps = ::sus::iter::__private::steps_between(
70+
static_cast<const Final*>(this)->start,
71+
static_cast<const Final*>(this)->finish);
7272
const ::sus::num::usize lower = steps.is_some() ? *steps : 0_usize;
7373
return ::sus::iter::SizeHint(lower, ::sus::move(steps));
7474
}
@@ -181,6 +181,9 @@ class Range final : public __private::RangeIter<Range<T>, T> {
181181
{
182182
return start == rhs.start && finish == rhs.finish;
183183
}
184+
185+
sus_class_trivially_relocatable_if_types(::sus::marker::unsafe_fn,
186+
decltype(start), decltype(finish));
184187
};
185188

186189
/// A range only bounded inclusively below (`start..`).
@@ -246,6 +249,9 @@ class RangeFrom final : public __private::RangeFromIter<RangeFrom<T>, T> {
246249
{
247250
return start == rhs.start;
248251
}
252+
253+
sus_class_trivially_relocatable_if_types(::sus::marker::unsafe_fn,
254+
decltype(start));
249255
};
250256

251257
/// A range only bounded exclusively above (`..end`).
@@ -301,6 +307,9 @@ class RangeTo final {
301307
{
302308
return finish == rhs.finish;
303309
}
310+
311+
sus_class_trivially_relocatable_if_types(::sus::marker::unsafe_fn,
312+
decltype(finish));
304313
};
305314

306315
/// An unbounded range (`..`).
@@ -311,7 +320,7 @@ class RangeTo final {
311320
/// A RangeFull<usize> can be constructed as a literal as `".."_r`.
312321
template <class T>
313322
requires(::sus::ops::Ord<T>)
314-
class RangeFull final {
323+
class [[sus_trivial_abi]] RangeFull final {
315324
public:
316325
RangeFull() = default;
317326

@@ -350,6 +359,8 @@ class RangeFull final {
350359
{
351360
return true;
352361
}
362+
363+
sus_class_trivially_relocatable(::sus::marker::unsafe_fn);
353364
};
354365

355366
} // namespace sus::ops

subspace/ops/range_unittest.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ static_assert(!sus::iter::Iterator<sus::ops::RangeFull<usize>, usize>);
6363
static_assert(!sus::iter::Iterator<sus::ops::Range<NoDefault>, NoDefault>);
6464
static_assert(!sus::iter::Iterator<sus::ops::RangeFrom<NoDefault>, NoDefault>);
6565

66+
// Range types are trivially relocatable if the inner type is.
67+
static_assert(sus::mem::relocate_by_memcpy<sus::ops::Range<usize>>);
68+
static_assert(sus::mem::relocate_by_memcpy<sus::ops::RangeFrom<usize>>);
69+
static_assert(sus::mem::relocate_by_memcpy<sus::ops::RangeTo<usize>>);
70+
// RangeFull has a 0 data size so it's not (0 is indistinguishable from the
71+
// error case and doesn't need to be memcpy'd).
72+
static_assert(!sus::mem::relocate_by_memcpy<sus::ops::RangeFull<usize>>);
73+
74+
// The types produced by the various literal syntaxes.
6675
static_assert(std::same_as<decltype(".."_r), sus::ops::RangeFull<usize>>);
6776
static_assert(std::same_as<decltype("1.."_r), sus::ops::RangeFrom<usize>>);
6877
static_assert(std::same_as<decltype("..2"_r), sus::ops::RangeTo<usize>>);

0 commit comments

Comments
 (0)