Skip to content

Commit fc230ff

Browse files
committed
Improve ... and ..= ranges working with std::ranges
This now works: for (0 ..= 10).std::views::take(5) do (i) { std::cout << i << std::endl; } Prints: 0 1 2 3 4
1 parent be17724 commit fc230ff

File tree

4 files changed

+86
-42
lines changed

4 files changed

+86
-42
lines changed

include/cpp2util.h

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,63 +2268,107 @@ inline auto make_args(int argc, char** argv) -> args
22682268
template<typename T>
22692269
struct 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>
23282372
range(T, U, bool = false) -> range<std::common_type_t<T, U>>;
23292373

23302374

regression-tests/test-results/msvc-2022-c++latest/pure2-regex_10_escapes.cpp.execution

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@ Running tests_10_escapes:
99
08_y: OK regex: foo(\h)bar parsed_regex: foo(\h)bar str: foo bar result_expr: $1 expected_results
1010
09_y: OK regex: (\H)(\h) parsed_regex: (\H)(\h) str: foo bar result_expr: $1-$2 expected_results o-
1111
10_y: OK regex: (\h)(\H) parsed_regex: (\h)(\H) str: foo bar result_expr: $1-$2 expected_results -b
12-
11_y: OK regex: foo(\v+)bar parsed_regex: foo(\v+)bar str: foo
12+
11_y: OK regex: foo(\v+)bar parsed_regex: foo(\v+)bar str: foo
13+
1314

15+
bar result_expr: $1 expected_results
16+
1417

15-
bar result_expr: $1 expected_results
1618

19+
12_y: OK regex: (\V+)(\v) parsed_regex: (\V+)(\v) str: foo
20+
1721

22+
bar result_expr: $1-$2 expected_results foo-
23+
13_y: OK regex: (\v+)(\V) parsed_regex: (\v+)(\V) str: foo
24+
1825

19-
12_y: OK regex: (\V+)(\v) parsed_regex: (\V+)(\v) str: foo
20-
21-
22-
bar result_expr: $1-$2 expected_results foo-
23-
13_y: OK regex: (\v+)(\V) parsed_regex: (\v+)(\V) str: foo
24-
25-
26-
bar result_expr: $1-$2 expected_results
27-
26+
bar result_expr: $1-$2 expected_results
27+
2828

2929
-b
30-
14_y: OK regex: foo(\v)bar parsed_regex: foo(\v)bar str: foobar result_expr: $1 expected_results
31-
15_y: OK regex: (\V)(\v) parsed_regex: (\V)(\v) str: foobar result_expr: $1-$2 expected_results o-
30+
14_y: OK regex: foo(\v)bar parsed_regex: foo(\v)bar str: foobar result_expr: $1 expected_results
31+
15_y: OK regex: (\V)(\v) parsed_regex: (\V)(\v) str: foobar result_expr: $1-$2 expected_results o-
3232
16_y: OK regex: (\v)(\V) parsed_regex: (\v)(\V) str: foobar result_expr: $1-$2 expected_results -b
3333
17_y: OK regex: foo\t\n\r\f\a\ebar parsed_regex: foo\t\n\r\f\a\ebar str: foo
3434
bar result_expr: $& expected_results foo

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.7.1 Build 9722:1112
2+
cppfront compiler v0.7.1 Build 9724:1613
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"9722:1112"
1+
"9724:1613"

0 commit comments

Comments
 (0)