openMSX
xrange.hh
Go to the documentation of this file.
1 #ifndef XRANGE_HH
2 #define XRANGE_HH
3 
4 // Utility to iterate over a range of numbers,
5 // modeled after python's xrange() function.
6 //
7 // Typically used as a more compact notation for some for-loop patterns:
8 //
9 // a) loop over [0, N)
10 //
11 // auto num = expensiveFunctionCall();
12 // for (decltype(num) i = 0; i < num; ++i) { ... }
13 //
14 // for (auto i : xrange(expensiveFunctionCall()) { ... }
15 //
16 // b) loop over [B, E)
17 //
18 // auto i = func1();
19 // auto end = func2();
20 // for (/**/; i < end; ++i) { ... }
21 //
22 // for (auto i : xrange(func1(), func2()) { ... }
23 //
24 // Note that when using the xrange utility you also don't need to worry about
25 // the correct type of the induction variable.
26 //
27 // Gcc is able to optimize the xrange() based loops to the same code as the
28 // equivalent 'old-style' for loop.
29 //
30 // In an earlier version of this utility I also implemented the possibility to
31 // specify a step size (currently the step size is always +1). Although I
32 // believe that code was correct I still removed it because it was quite tricky
33 // (getting the stop condition correct is not trivial) and we don't need it
34 // currently.
35 
36 template<typename T> class XRange
37 {
38 public:
39  class XRangeIter
40  {
41  public:
42  using difference_type = ptrdiff_t;
43  using value_type = T;
44  using pointer = T*;
45  using reference = T&;
46  using iterator_category = std::random_access_iterator_tag;
47 
48  explicit XRangeIter(T x_)
49  : x(x_)
50  {
51  }
52 
53  // ForwardIterator
54  T operator*() const
55  {
56  return x;
57  }
58 
60  {
61  ++x;
62  return *this;
63  }
65  {
66  auto copy = *this;
67  ++x;
68  return copy;
69  }
70 
71  bool operator==(const XRangeIter& other) const
72  {
73  return x == other.x;
74  }
75  bool operator!=(const XRangeIter& other) const
76  {
77  return x != other.x;
78  }
79 
80  // BidirectionalIterator
82  {
83  --x;
84  return *this;
85  }
87  {
88  auto copy = *this;
89  --x;
90  return copy;
91  }
92 
93  // RandomAccessIterator
95  {
96  x += n;
97  return *this;
98  }
100  {
101  x -= n;
102  return *this;
103  }
104 
106  {
107  i += n;
108  return i;
109  }
111  {
112  i += n;
113  return i;
114  }
116  {
117  i -= n;
118  return i;
119  }
120 
121  friend difference_type operator-(const XRangeIter& i, const XRangeIter& j)
122  {
123  return i.x - j.x;
124  }
125 
127  {
128  return *(*this + n);
129  }
130 
131  friend bool operator<(const XRangeIter& i, const XRangeIter& j)
132  {
133  return i.x < j.x;
134  }
135  friend bool operator<=(const XRangeIter& i, const XRangeIter& j)
136  {
137  return i.x <= j.x;
138  }
139  friend bool operator>(const XRangeIter& i, const XRangeIter& j)
140  {
141  return i.x > j.x;
142  }
143  friend bool operator>=(const XRangeIter& i, const XRangeIter& j)
144  {
145  return i.x >= j.x;
146  }
147 
148  private:
149  T x;
150  };
151 
152  explicit XRange(T e_)
153  : b(0), e(e_)
154  {
155  }
156 
157  XRange(T b_, T e_)
158  : b(b_), e(e_)
159  {
160  }
161 
162  auto begin() const { return XRangeIter(b); }
163  auto end() const { return XRangeIter(e); }
164 
165 private:
166  const T b;
167  const T e;
168 };
169 
170 template<typename T> inline auto xrange(T e)
171 {
172  return XRange<T>(e);
173 }
174 template<typename T> inline auto xrange(T b, T e)
175 {
176  return XRange<T>(b, e);
177 }
178 
179 #endif
T operator*() const
Definition: xrange.hh:54
friend XRangeIter operator-(XRangeIter i, difference_type n)
Definition: xrange.hh:115
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:149
XRange(T b_, T e_)
Definition: xrange.hh:157
auto xrange(T e)
Definition: xrange.hh:170
friend XRangeIter operator+(difference_type n, XRangeIter i)
Definition: xrange.hh:110
friend bool operator>(const XRangeIter &i, const XRangeIter &j)
Definition: xrange.hh:139
friend bool operator<(const XRangeIter &i, const XRangeIter &j)
Definition: xrange.hh:131
friend XRangeIter operator+(XRangeIter i, difference_type n)
Definition: xrange.hh:105
XRange(T e_)
Definition: xrange.hh:152
XRangeIter operator--(int)
Definition: xrange.hh:86
friend bool operator<=(const XRangeIter &i, const XRangeIter &j)
Definition: xrange.hh:135
friend bool operator>=(const XRangeIter &i, const XRangeIter &j)
Definition: xrange.hh:143
XRangeIter & operator-=(difference_type n)
Definition: xrange.hh:99
XRangeIter & operator+=(difference_type n)
Definition: xrange.hh:94
bool operator!=(const XRangeIter &other) const
Definition: xrange.hh:75
friend difference_type operator-(const XRangeIter &i, const XRangeIter &j)
Definition: xrange.hh:121
ptrdiff_t difference_type
Definition: xrange.hh:42
bool operator==(const XRangeIter &other) const
Definition: xrange.hh:71
XRangeIter & operator++()
Definition: xrange.hh:59
auto end() const
Definition: xrange.hh:163
auto begin() const
Definition: xrange.hh:162
Definition: xrange.hh:36
XRangeIter & operator--()
Definition: xrange.hh:81
T operator[](difference_type n)
Definition: xrange.hh:126
std::random_access_iterator_tag iterator_category
Definition: xrange.hh:46
XRangeIter operator++(int)
Definition: xrange.hh:64
XRangeIter(T x_)
Definition: xrange.hh:48