@@ -2268,63 +2268,107 @@ inline auto make_args(int argc, char** argv) -> args
22682268template <typename T>
22692269struct range
22702270{
2271+ using difference_type = std::ptrdiff_t ;
2272+ using value_type = T;
2273+ using pointer = T*;
2274+ using reference = T&;
2275+
22712276 range (
2272- T const & f,
2273- T const & l,
2277+ T const & f,
2278+ T const & l,
22742279 bool include_last = false
2275- )
2280+ )
22762281 : first{ f }
2277- , last{ l }
2278- {
2279- if (include_last) {
2280- ++last;
2282+ , last{ l }
2283+ {
2284+ if (include_last) {
2285+ ++last;
22812286 }
22822287 }
22832288
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+ {
22852302 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+
22862311 iterator (T const & f, T const & l, T start) : first{ f }, last{ l }, curr{ start } {}
22872312
2288- auto operator *() const {
2313+ auto operator <=>(iterator const &) const = default ;
2314+
2315+ auto operator *() const -> T {
22892316 if (curr != last) { return curr; }
2290- else { return T{}; }
2317+ else { return T{}; }
22912318 }
22922319
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{}; }
22962330 }
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; }
23022331
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); }
23042347
23052348 private:
2306- T first;
2307- T last;
2308- T curr;
2349+ T first = T{} ;
2350+ T last = T{} ;
2351+ T curr = T{} ;
23092352 };
23102353
23112354 auto begin () const -> iterator { return iterator{ first, last, first }; }
23122355 auto end () const -> iterator { return iterator{ first, last, last }; }
23132356 auto cbegin () const -> iterator { return begin (); }
23142357 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 ()); }
23162359 auto ssize () const -> int { return last - first; }
23172360
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{}; }
23212364 }
23222365
23232366 T first;
23242367 T last;
23252368};
23262369
2327- template <class T , class U >
2370+
2371+ template <typename T, typename U>
23282372range (T, U, bool = false ) -> range<std::common_type_t<T, U>>;
23292373
23302374
0 commit comments