@@ -25,12 +25,23 @@ namespace sus::ops {
25
25
// / range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
26
26
template <class T , class I >
27
27
concept RangeBounds = requires (const T& t, T v, I i) {
28
- { t.start_bound () } -> std::same_as<::sus::option::Option<const I&>>;
28
+ { t.start_bound () } -> std::same_as<::sus::option::Option<const I&>>;
29
29
{ t.end_bound () } -> std::same_as<::sus::option::Option<const I&>>;
30
- // Rvalue overloads must not exist as they would return a reference to a temporary.
30
+ // Rvalue overloads must not exist as they would return a reference to a
31
+ // temporary.
31
32
requires !requires { ::sus::move (v).start_bound (); };
32
33
requires !requires { ::sus::move (v).end_bound (); };
33
34
{ t.contains (i) } -> std::same_as<bool >;
35
+ // These should return a RangeBounds, but we're unable to check that here as
36
+ // the type may return itself and the concept would be cyclical and thus
37
+ // become false.
38
+ { ::sus::move (v).start_at (i) };
39
+ { ::sus::move (v).end_at (i) };
40
+ // start_at() and end_at() are rvalue methods.
41
+ requires !requires { t.start_at (i); };
42
+ requires !requires { t.end_at (i); };
43
+ requires !requires { v.start_at (i); };
44
+ requires !requires { v.end_at (i); };
34
45
};
35
46
36
47
// / A (half-open) range bounded inclusively below and exclusively above
@@ -55,9 +66,8 @@ class Range final : public ::sus::iter::IteratorImpl<Range<T>, T> {
55
66
constexpr Range () noexcept
56
67
requires(::sus::construct::Default<T>)
57
68
= default;
58
- static constexpr Range with (T start, T finish) noexcept {
59
- return Range (::sus::move (start), ::sus::move (finish));
60
- }
69
+ constexpr Range (T start, T finish) noexcept
70
+ : start(::sus::move(start)), finish(::sus::move(finish)) {}
61
71
62
72
// / Returns true if `item` is contained in the range.
63
73
//
@@ -85,6 +95,17 @@ class Range final : public ::sus::iter::IteratorImpl<Range<T>, T> {
85
95
// / The range is empty if either side is incomparable, such as `f32::NAN`.
86
96
constexpr bool is_empty () const noexcept { return !(start < finish); }
87
97
98
+ // / Return a new Range that starts at `t` and ends where the original Range
99
+ // / did.
100
+ constexpr Range start_at (T t) && noexcept {
101
+ return Range (::sus::move (t), ::sus::move (finish));
102
+ }
103
+ // / Return a new Range that starts at where the original Range did and ends at
104
+ // / `t`.
105
+ constexpr Range end_at (T t) && noexcept {
106
+ return Range (::sus::move (start), ::sus::move (t));
107
+ }
108
+
88
109
// sus::iter::Iterator trait.
89
110
Option<T> next () noexcept final {
90
111
if (start == finish) return Option<T>::none ();
@@ -108,9 +129,12 @@ class Range final : public ::sus::iter::IteratorImpl<Range<T>, T> {
108
129
// TODO: Provide and test overrides of Iterator min(), max(), count(),
109
130
// advance_by(), etc that can be done efficiently here.
110
131
111
- private:
112
- constexpr Range (T start, T finish) noexcept
113
- : start(::sus::move(start)), finish(::sus::move(finish)) {}
132
+ // sus::ops::Eq trait
133
+ constexpr bool operator ==(const Range& rhs) const noexcept
134
+ requires Eq<T>
135
+ {
136
+ return start == rhs.start && finish == rhs.finish ;
137
+ }
114
138
};
115
139
116
140
// / A range only bounded inclusively below (`start..`).
@@ -137,9 +161,7 @@ class RangeFrom final : public ::sus::iter::IteratorImpl<RangeFrom<T>, T> {
137
161
constexpr RangeFrom () noexcept
138
162
requires(::sus::construct::Default<T>)
139
163
= default;
140
- static constexpr RangeFrom with (T start) noexcept {
141
- return RangeFrom (::sus::move (start));
142
- }
164
+ constexpr RangeFrom (T start) noexcept : start(::sus::move(start)) {}
143
165
144
166
// / Returns true if `item` is contained in the range.
145
167
// /
@@ -162,6 +184,16 @@ class RangeFrom final : public ::sus::iter::IteratorImpl<RangeFrom<T>, T> {
162
184
}
163
185
constexpr ::sus::option::Option<const T&> end_bound () && = delete;
164
186
187
+ // / Return a new RangeFrom that starts at `t` and still has no end.
188
+ constexpr RangeFrom start_at (T t) && noexcept {
189
+ return RangeFrom (::sus::move (t));
190
+ }
191
+ // / Return a new Range that starts at where the original Range did and ends at
192
+ // / `t`.
193
+ constexpr Range<T> end_at (T t) && noexcept {
194
+ return Range<T>(::sus::move (start), ::sus::move (t));
195
+ }
196
+
165
197
// sus::iter::Iterator trait.
166
198
Option<T> next () noexcept final {
167
199
return Option<T>::some (::sus::mem::replace (start, start + 1u ));
@@ -170,8 +202,12 @@ class RangeFrom final : public ::sus::iter::IteratorImpl<RangeFrom<T>, T> {
170
202
// TODO: Provide and test overrides of Iterator min(), advance_by(), etc
171
203
// that can be done efficiently here.
172
204
173
- private:
174
- constexpr RangeFrom (T start) noexcept : start(::sus::move(start)) {}
205
+ // sus::ops::Eq trait
206
+ constexpr bool operator ==(const RangeFrom& rhs) const noexcept
207
+ requires Eq<T>
208
+ {
209
+ return start == rhs.start ;
210
+ }
175
211
};
176
212
177
213
// / A range only bounded exclusively above (`..end`).
@@ -190,9 +226,7 @@ class RangeTo final {
190
226
constexpr RangeTo () noexcept
191
227
requires(::sus::construct::Default<T>)
192
228
= default;
193
- static constexpr RangeTo with (T finish) noexcept {
194
- return RangeTo (::sus::move (finish));
195
- }
229
+ constexpr RangeTo (T finish) noexcept : finish(::sus::move(finish)) {}
196
230
197
231
// / Returns true if `item` is contained in the range.
198
232
// /
@@ -215,8 +249,20 @@ class RangeTo final {
215
249
}
216
250
constexpr ::sus::option::Option<const T&> end_bound () && = delete;
217
251
218
- private:
219
- constexpr RangeTo (T finish) noexcept : finish(::sus::move(finish)) {}
252
+ // / Return a new Range that starts at `t` and ends where the original Range
253
+ // / did.
254
+ constexpr Range<T> start_at (T t) && noexcept {
255
+ return Range<T>(::sus::move (t), ::sus::move (finish));
256
+ }
257
+ // / Return a new Range that still has no start and ends at `t`.
258
+ constexpr RangeTo end_at (T t) && noexcept { return RangeTo (::sus::move (t)); }
259
+
260
+ // sus::ops::Eq trait
261
+ constexpr bool operator ==(const RangeTo& rhs) const noexcept
262
+ requires Eq<T>
263
+ {
264
+ return finish == rhs.finish ;
265
+ }
220
266
};
221
267
222
268
// / An unbounded range (`..`).
@@ -250,6 +296,22 @@ class RangeFull final {
250
296
return ::sus::option::Option<const T&>::none ();
251
297
}
252
298
constexpr ::sus::option::Option<const T&> end_bound () && = delete;
299
+
300
+ // / Return a new Range that starts at `t` and has no end.
301
+ constexpr RangeFrom<T> start_at (T t) && noexcept {
302
+ return RangeFrom<T>(::sus::move (t));
303
+ }
304
+ // / Return a new Range that has no start and ends at `t`.
305
+ constexpr RangeTo<T> end_at (T t) && noexcept {
306
+ return RangeTo<T>(::sus::move (t));
307
+ }
308
+
309
+ // sus::ops::Eq trait
310
+ constexpr bool operator ==(const RangeFull& rhs) const noexcept
311
+ requires Eq<T>
312
+ {
313
+ return true ;
314
+ }
253
315
};
254
316
255
317
} // namespace sus::ops
0 commit comments