FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

New method range_proxy::size() to know the size of the range. #3 · klmr/cpp11-range@a47d992 · GitHub

Repository navigation

Commit a47d992

Browse files
committed
New method range_proxy::size() to know the size of the range. #3
* Simplify `size` implementation Author: Konrad Rudolph <konrad.rudolph@gmail.com> * Use name “iterator” consistently Author: Konrad Rudolph <konrad.rudolph@gmail.com> * Method range_proxy::step_range_proxy::size() * Implementation updated from the PR discussion. * Tests were added to verify the results Author: Arnaud Barré <alzathar@Moveck-C05.local> * New method range_proxy::size() to know the size of the range. Author: Arnaud Barré <arnaud.barre@gmail.com>
1 parent 5411558 commit a47d992

2 files changed

Lines changed: 127 additions & 68 deletions

File tree

‎range.hpp‎

Lines changed: 82 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef UTIL_LANG_RANGE_HPP
22
#define UTIL_LANG_RANGE_HPP
33

4+
#include <cmath>
45
#include <iterator>
56
#include <type_traits>
67

@@ -42,120 +43,133 @@ struct range_iter_base : std::iterator<std::input_iterator_tag, T> {
4243
} // namespace detail
4344

4445
template <typename T>
45-
struct range_proxy {
46+
struct step_range_proxy {
4647
struct iterator : detail::range_iter_base<T> {
47-
iterator(T current) : detail::range_iter_base<T>(current) { }
48-
};
48+
iterator(T current, T step)
49+
: detail::range_iter_base<T>(current), step_(step) { }
4950

50-
struct step_range_proxy {
51-
struct iter : detail::range_iter_base<T> {
52-
iter(T current, T step)
53-
: detail::range_iter_base<T>(current), step(step) { }
51+
using detail::range_iter_base<T>::current;
5452

55-
using detail::range_iter_base<T>::current;
53+
iterator& operator ++() {
54+
current += step_;
55+
return *this;
56+
}
5657

57-
iter& operator ++() {
58-
current += step;
59-
return *this;
60-
}
58+
iterator operator ++(int) {
59+
auto copy = *this;
60+
++*this;
61+
return copy;
62+
}
6163

62-
iter operator ++(int) {
63-
auto copy = *this;
64-
++*this;
65-
return copy;
66-
}
64+
// Loses commutativity. Iterator-based ranges are simply broken. :-(
65+
bool operator ==(iterator const& other) const {
66+
return step_ > 0 ? current >= other.current
67+
: current < other.current;
68+
}
6769

68-
// Loses commutativity. Iterator-based ranges are simply broken. :-(
69-
bool operator ==(iter const& other) const {
70-
return step > 0 ? current >= other.current
71-
: current < other.current;
72-
}
70+
bool operator !=(iterator const& other) const {
71+
return not (*this == other);
72+
}
7373

74-
bool operator !=(iter const& other) const {
75-
return not (*this == other);
76-
}
74+
T step_;
75+
};
7776

78-
private:
79-
T step;
80-
};
77+
step_range_proxy(T begin, T end, T step)
78+
: begin_(begin, step), end_(end, step) { }
8179

82-
step_range_proxy(T begin, T end, T step)
83-
: begin_(begin, step), end_(end, step) { }
80+
iterator begin() const { return begin_; }
8481

85-
iter begin() const { return begin_; }
82+
iterator end() const { return end_; }
8683

87-
iter end() const { return end_; }
84+
std::size_t size() const {
85+
if (*end_ >= *begin_) {
86+
// Increasing and empty range
87+
if (begin_.step_ < T{0}) return 0;
88+
} else {
89+
// Decreasing range
90+
if (begin_.step_ > T{0}) return 0;
91+
}
92+
return std::ceil(std::abs(static_cast<double>(*end_ - *begin_) / begin_.step_));
93+
}
8894

89-
private:
90-
iter begin_;
91-
iter end_;
95+
private:
96+
iterator begin_;
97+
iterator end_;
98+
};
99+
100+
template <typename T>
101+
struct range_proxy {
102+
struct iterator : detail::range_iter_base<T> {
103+
iterator(T current) : detail::range_iter_base<T>(current) { }
92104
};
93105

94106
range_proxy(T begin, T end) : begin_(begin), end_(end) { }
95107

96-
step_range_proxy step(T step) {
108+
step_range_proxy<T> step(T step) {
97109
return {*begin_, *end_, step};
98110
}
99111

100112
iterator begin() const { return begin_; }
101-
102113
iterator end() const { return end_; }
103114

115+
std::size_t size() const { return *end_ - *begin_; }
116+
104117
private:
105118
iterator begin_;
106119
iterator end_;
107120
};
108121

109122
template <typename T>
110-
struct infinite_range_proxy {
123+
struct step_inf_range_proxy {
111124
struct iterator : detail::range_iter_base<T> {
112-
iterator(T current = T()) : detail::range_iter_base<T>(current) { }
125+
iterator(T current = T(), T step = T())
126+
: detail::range_iter_base<T>(current), step(step) { }
113127

114-
bool operator ==(iterator const&) const { return false; }
128+
using detail::range_iter_base<T>::current;
115129

116-
bool operator !=(iterator const&) const { return true; }
117-
};
130+
iterator& operator ++() {
131+
current += step;
132+
return *this;
133+
}
118134

119-
struct step_range_proxy {
120-
struct iter : detail::range_iter_base<T> {
121-
iter(T current = T(), T step = T())
122-
: detail::range_iter_base<T>(current), step(step) { }
135+
iterator operator ++(int) {
136+
auto copy = *this;
137+
++*this;
138+
return copy;
139+
}
123140

124-
using detail::range_iter_base<T>::current;
141+
bool operator ==(iterator const&) const { return false; }
125142

126-
iter& operator ++() {
127-
current += step;
128-
return *this;
129-
}
143+
bool operator !=(iterator const&) const { return true; }
130144

131-
iter operator ++(int) {
132-
auto copy = *this;
133-
++*this;
134-
return copy;
135-
}
145+
private:
146+
T step;
147+
};
136148

137-
bool operator ==(iter const&) const { return false; }
149+
step_inf_range_proxy(T begin, T step) : begin_(begin, step) { }
138150

139-
bool operator !=(iter const&) const { return true; }
151+
iterator begin() const { return begin_; }
140152

141-
private:
142-
T step;
143-
};
153+
iterator end() const { return iterator(); }
144154

145-
step_range_proxy(T begin, T step) : begin_(begin, step) { }
155+
private:
156+
iterator begin_;
157+
};
146158

147-
iter begin() const { return begin_; }
159+
template <typename T>
160+
struct infinite_range_proxy {
161+
struct iterator : detail::range_iter_base<T> {
162+
iterator(T current = T()) : detail::range_iter_base<T>(current) { }
148163

149-
iter end() const { return iter(); }
164+
bool operator ==(iterator const&) const { return false; }
150165

151-
private:
152-
iter begin_;
166+
bool operator !=(iterator const&) const { return true; }
153167
};
154168

155169
infinite_range_proxy(T begin) : begin_(begin) { }
156170

157-
step_range_proxy step(T step) {
158-
return step_range_proxy(*begin_, step);
171+
step_inf_range_proxy<T> step(T step) {
172+
return {*begin_, step};
159173
}
160174

161175
iterator begin() const { return begin_; }

‎test.cpp‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,45 @@ void print_range(R const& range) {
1212
std::cout << "\n";
1313
}
1414

15+
template <typename R>
16+
std::size_t manual_range_size(R const& range) {
17+
std::size_t size = 0;
18+
for (auto const& _ : range) ++size, (void) _;
19+
return size;
20+
}
21+
22+
namespace util { namespace lang {
23+
24+
// template <typename T>
25+
// struct is_a_step_range : std::false_type {};
26+
27+
// template <typename T>
28+
// struct is_a_step_range<typename range_proxy<T>::step_range_proxy> : std::true_type {};
29+
30+
template <typename T>
31+
std::ostream& operator <<(std::ostream& out, step_range_proxy<T> const& r) {
32+
return out << "range(" << *r.begin() << ", " << *r.end() << ")"
33+
<< ".step(" << r.begin().step_ << ")";
34+
}
35+
36+
template <typename T>
37+
std::ostream& operator <<(std::ostream& out, range_proxy<T> const& r) {
38+
return out << "range(" << *r.begin() << ", " << *r.end() << ")";
39+
}
40+
41+
}}
42+
43+
template <typename R>
44+
void test_range_size(R const& range) {
45+
auto const real_size = manual_range_size(R{range});
46+
if (real_size == range.size()) {
47+
std::cout << range << ".size() = " << real_size << "\n";
48+
} else {
49+
std::cout << "ERROR: " << range << ".size() ≠ " << real_size
50+
<< " (was " << range.size() << ")!\n";
51+
}
52+
}
53+
1554
int main() {
1655
using std::cout;
1756
using util::lang::range;
@@ -64,4 +103,10 @@ int main() {
64103
print_range(range(8, 1).step(-2));
65104
print_range(range(8.0, 1.0).step(-2.0));
66105
cout << "\n";
106+
107+
test_range_size(range(1, 8).step(2));
108+
test_range_size(range(8.0, 1.0).step(-2.0));
109+
test_range_size(range(8, 1).step(-2));
110+
test_range_size(range(0.1, 0.11).step(2));
111+
test_range_size(range(-7, 1).step(7));
67112
}

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL