@@ -2268,63 +2268,107 @@ inline auto make_args(int argc, char** argv) -> args
2268
2268
template <typename T>
2269
2269
struct range
2270
2270
{
2271
+ using difference_type = std::ptrdiff_t ;
2272
+ using value_type = T;
2273
+ using pointer = T*;
2274
+ using reference = T&;
2275
+
2271
2276
range (
2272
- T const & f,
2273
- T const & l,
2277
+ T const & f,
2278
+ T const & l,
2274
2279
bool include_last = false
2275
- )
2280
+ )
2276
2281
: first{ f }
2277
- , last{ l }
2278
- {
2279
- if (include_last) {
2280
- ++last;
2282
+ , last{ l }
2283
+ {
2284
+ if (include_last) {
2285
+ ++last;
2281
2286
}
2282
2287
}
2283
2288
2284
- class iterator {
2289
+ // If T is numeric, use explicit narrowing to avoid compiler warnings
2290
+ static auto inc_by (T& t, difference_type i) -> T&
2291
+ {
2292
+ if constexpr (std::integral<T>) {
2293
+ return t += unsafe_narrow<T>(i);
2294
+ }
2295
+ else {
2296
+ return t += i;
2297
+ }
2298
+ }
2299
+
2300
+ class iterator
2301
+ {
2285
2302
public:
2303
+ using difference_type = std::ptrdiff_t ;
2304
+ using value_type = T;
2305
+ using pointer = T*;
2306
+ using reference = T&;
2307
+ using iterator_category = std::random_access_iterator_tag;
2308
+
2309
+ iterator () { }
2310
+
2286
2311
iterator (T const & f, T const & l, T start) : first{ f }, last{ l }, curr{ start } {}
2287
2312
2288
- auto operator *() const {
2313
+ auto operator <=>(iterator const &) const = default ;
2314
+
2315
+ auto operator *() const -> T {
2289
2316
if (curr != last) { return curr; }
2290
- else { return T{}; }
2317
+ else { return T{}; }
2291
2318
}
2292
2319
2293
- auto operator +(int i) -> iterator {
2294
- if (i > 0 ) { return { first, last, std::min (curr + i, last) }; }
2295
- else { return { first, last, std::max (curr + i, 0 ) }; }
2320
+ auto operator ++() -> iterator& { if (curr != last ) { ++curr; } return *this ; }
2321
+ auto operator --() -> iterator& { if (curr != first) { --curr; } return *this ; }
2322
+ auto operator ++(int ) -> iterator { auto old = *this ; ++*this ; return old; }
2323
+ auto operator --(int ) -> iterator { auto old = *this ; ++*this ; return old; }
2324
+
2325
+ // And now all the random-access operations (valid if T is random-access)
2326
+ //
2327
+ auto operator [](difference_type i) const -> T {
2328
+ if (curr + i != last) { return curr + i; }
2329
+ else { return T{}; }
2296
2330
}
2297
- auto operator -(int i) -> iterator { return operator +(-i); }
2298
- auto operator ++() -> iterator& { if (curr != last ) { ++curr; } return *this ; }
2299
- auto operator --() -> iterator& { if (curr != first) { --curr; } return *this ; }
2300
- auto operator ++(int ) -> iterator { auto old = *this ; ++*this ; return old; }
2301
- auto operator --(int ) -> iterator { auto old = *this ; ++*this ; return old; }
2302
2331
2303
- auto operator <=>(iterator const &) const = default ;
2332
+ auto operator +=(difference_type i) -> iterator& { if (curr + i <= last ) { inc_by (curr, i); } else { curr = last; } return *this ; }
2333
+ auto operator -=(difference_type i) -> iterator& { if (curr - i >= first) { inc_by (curr, -i); } else { curr = first; } return *this ; }
2334
+
2335
+ friend
2336
+ auto operator + (difference_type i, iterator const & this_) -> iterator { auto ret = *this_; return ret += i; }
2337
+
2338
+ auto operator + (difference_type i ) const -> iterator { auto ret = *this ; return ret += i; }
2339
+ auto operator - (difference_type i ) const -> iterator { auto ret = *this ; return ret -= i; }
2340
+ auto operator - (iterator that) const -> difference_type { return that.curr - curr; }
2341
+
2342
+ // auto operator+(difference_type i) -> iterator {
2343
+ // if (i > 0) { return { first, last, std::min(curr + i, last) }; }
2344
+ // else { return { first, last, std::max(curr + i, 0) }; }
2345
+ // }
2346
+ // auto operator- (difference_type i) -> iterator { return operator+(-i); }
2304
2347
2305
2348
private:
2306
- T first;
2307
- T last;
2308
- T curr;
2349
+ T first = T{} ;
2350
+ T last = T{} ;
2351
+ T curr = T{} ;
2309
2352
};
2310
2353
2311
2354
auto begin () const -> iterator { return iterator{ first, last, first }; }
2312
2355
auto end () const -> iterator { return iterator{ first, last, last }; }
2313
2356
auto cbegin () const -> iterator { return begin (); }
2314
2357
auto cend () const -> iterator { return end (); }
2315
- auto size () const -> std::size_t { return cpp2:: unsafe_narrow<std::size_t >(ssize ()); }
2358
+ auto size () const -> std::size_t { return unsafe_narrow<std::size_t >(ssize ()); }
2316
2359
auto ssize () const -> int { return last - first; }
2317
2360
2318
- auto operator [](int i) const {
2319
- if (0 <= i && i < ssize ()) { return first + i; }
2320
- else { return T{}; }
2361
+ auto operator [](difference_type i) const {
2362
+ if (0 <= i && i < ssize ()) { return first + i; }
2363
+ else { return T{}; }
2321
2364
}
2322
2365
2323
2366
T first;
2324
2367
T last;
2325
2368
};
2326
2369
2327
- template <class T , class U >
2370
+
2371
+ template <typename T, typename U>
2328
2372
range (T, U, bool = false ) -> range<std::common_type_t<T, U>>;
2329
2373
2330
2374
0 commit comments