openMSX
view.hh
Go to the documentation of this file.
1 #ifndef VIEW_HH
2 #define VIEW_HH
3 
4 #include "semiregular.hh"
5 #include <algorithm>
6 #include <iterator>
7 #include <tuple>
8 #include <type_traits>
9 
10 namespace view {
11 namespace detail {
12 
13 template<typename Iterator>
14 [[nodiscard]] Iterator safe_next(Iterator first, Iterator last, size_t n, std::input_iterator_tag)
15 {
16  while (n-- && (first != last)) ++first;
17  return first;
18 }
19 
20 template<typename Iterator>
21 [[nodiscard]] Iterator safe_next(Iterator first, Iterator last, size_t n, std::random_access_iterator_tag)
22 {
23  return first + std::min<size_t>(n, last - first);
24 }
25 
26 template<typename Iterator>
27 [[nodiscard]] Iterator safe_prev(Iterator first, Iterator last, size_t n, std::bidirectional_iterator_tag)
28 {
29  while (n-- && (first != last)) --last;
30  return last;
31 }
32 
33 template<typename Iterator>
34 [[nodiscard]] Iterator safe_prev(Iterator first, Iterator last, size_t n, std::random_access_iterator_tag)
35 {
36  return last - std::min<size_t>(n, last - first);
37 }
38 
39 
40 template<typename Range>
41 class Drop
42 {
43 public:
44  Drop(Range&& range_, size_t n_)
45  : range(std::forward<Range>(range_))
46  , n(n_)
47  {
48  }
49 
50  [[nodiscard]] auto begin() const {
51  using Iterator = decltype(std::begin(range));
52  return safe_next(std::begin(range), std::end(range), n,
53  typename std::iterator_traits<Iterator>::iterator_category());
54  }
55 
56  [[nodiscard]] auto end() const {
57  return std::end(range);
58  }
59 
60 private:
61  Range range;
62  size_t n;
63 };
64 
65 
66 template<typename Range>
67 class DropBack
68 {
69 public:
70  DropBack(Range&& range_, size_t n_)
71  : range(std::forward<Range>(range_))
72  , n(n_)
73  {
74  }
75 
76  [[nodiscard]] auto begin() const {
77  return std::begin(range);
78  }
79 
80  [[nodiscard]] auto end() const {
81  using Iterator = decltype(std::begin(range));
82  return safe_prev(std::begin(range), std::end(range), n,
83  typename std::iterator_traits<Iterator>::iterator_category());
84  }
85 
86 private:
87  Range range;
88  size_t n;
89 };
90 
91 
92 template<typename Range>
93 class Reverse
94 {
95 public:
96  explicit Reverse(Range&& range_)
97  : range(std::forward<Range>(range_))
98  {
99  }
100 
101  [[nodiscard]] auto begin() const { return range.rbegin(); }
102  [[nodiscard]] auto begin() { return range.rbegin(); }
103  [[nodiscard]] auto end() const { return range.rend(); }
104  [[nodiscard]] auto end() { return range.rend(); }
105  [[nodiscard]] auto rbegin() const { return range.begin(); }
106  [[nodiscard]] auto rbegin() { return range.begin(); }
107  [[nodiscard]] auto rend() const { return range.end(); }
108  [[nodiscard]] auto rend() { return range.end(); }
109 
110 private:
111  Range range;
112 };
113 
114 
115 template<typename Iterator, typename UnaryOp> class TransformIterator
116 {
117 public:
118  using return_type = decltype(std::declval<UnaryOp>()(*std::declval<Iterator>()));
119  using value_type = std::remove_reference_t<return_type>;
121  using pointer = value_type*;
122  using difference_type = typename std::iterator_traits<Iterator>::difference_type;
123  using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
124 
125 public:
126  TransformIterator() = default;
127 
128  TransformIterator(Iterator it_, UnaryOp op_)
129  : storage(it_, op_)
130  {
131  }
132 
133  // InputIterator, ForwardIterator
134 
135  [[nodiscard]] return_type operator*() const { return op()(*it()); }
136 
137  // pointer operator->() const not defined
138 
140  {
141  ++it();
142  return *this;
143  }
144 
146  {
147  auto copy = *this;
148  ++it();
149  return copy;
150  }
151 
152  [[nodiscard]] friend bool operator==(const TransformIterator& x, const TransformIterator& y)
153  {
154  return x.it() == y.it();
155  }
156 
157  [[nodiscard]] friend bool operator!=(const TransformIterator& x, const TransformIterator& y)
158  {
159  return x.it() != y.it();
160  }
161 
162  // BidirectionalIterator
163 
165  {
166  --it();
167  return *this;
168  }
169 
171  {
172  auto copy = *this;
173  --it();
174  return copy;
175  }
176 
177  // RandomAccessIterator
178 
180  {
181  it() += n;
182  return *this;
183  }
184 
186  {
187  it() -= n;
188  return *this;
189  }
190 
192  {
193  x += n;
194  return x;
195  }
197  {
198  x += n;
199  return x;
200  }
201 
203  {
204  x -= n;
205  return x;
206  }
207 
208  [[nodiscard]] friend difference_type operator-(const TransformIterator& x, const TransformIterator& y)
209  {
210  return x.it() - y.it();
211  }
212 
214  {
215  return *(*this + n);
216  }
217 
218  [[nodiscard]] friend bool operator<(const TransformIterator& x, const TransformIterator& y)
219  {
220  return x.it() < y.it();
221  }
222  [[nodiscard]] friend bool operator<=(const TransformIterator& x, const TransformIterator& y)
223  {
224  return x.it() <= y.it();
225  }
226  [[nodiscard]] friend bool operator>(const TransformIterator& x, const TransformIterator& y)
227  {
228  return x.it() > y.it();
229  }
230  [[nodiscard]] friend bool operator>=(const TransformIterator& x, const TransformIterator& y)
231  {
232  return x.it() >= y.it();
233  }
234 
235 private:
236  std::tuple<Iterator, semiregular_t<UnaryOp>> storage;
237 
238  [[nodiscard]] Iterator& it() { return std::get<0>(storage); }
239  [[nodiscard]] const Iterator& it() const { return std::get<0>(storage); }
240  [[nodiscard]] UnaryOp& op() { return std::get<1>(storage); }
241  [[nodiscard]] const UnaryOp& op() const { return std::get<1>(storage); }
242 };
243 
244 template<typename Range, typename UnaryOp> class Transform
245 {
246 public:
247  Transform(Range&& range_, UnaryOp op_)
248  : storage(std::forward<Range>(range_), op_)
249  {
250  }
251 
252  [[nodiscard]] auto begin() const
253  {
254  return TransformIterator(std::begin(range()), op());
255  }
256  [[nodiscard]] auto end() const
257  {
258  return TransformIterator(std::end(range()), op());
259  }
260  [[nodiscard]] auto rbegin() const
261  {
262  return TransformIterator(std::rbegin(range()), op());
263  }
264  [[nodiscard]] auto rend() const
265  {
266  return TransformIterator(std::rend(range()), op());
267  }
268 
269  [[nodiscard]] auto size() const { return range().size(); }
270  [[nodiscard]] auto empty() const { return range().empty(); }
271 
272  [[nodiscard]] auto front() const { return op()(range().front()); }
273  [[nodiscard]] auto back() const { return op()(range().back()); }
274 
275  [[nodiscard]] auto operator[](size_t idx) const { return op()(range()[idx]); }
276 
277 private:
278  std::tuple<Range, UnaryOp> storage;
279 
280  [[nodiscard]] const Range& range() const { return std::get<0>(storage); }
281  [[nodiscard]] const UnaryOp& op() const { return std::get<1>(storage); }
282 };
283 
284 
285 } // namespace detail
286 
287 template<typename Range>
288 [[nodiscard]] auto drop(Range&& range, size_t n)
289 {
290  return detail::Drop<Range>(std::forward<Range>(range), n);
291 }
292 
293 template<typename Range>
294 [[nodiscard]] auto drop_back(Range&& range, size_t n)
295 {
296  return detail::DropBack<Range>(std::forward<Range>(range), n);
297 }
298 
299 template<typename Range>
300 [[nodiscard]] auto reverse(Range&& range)
301 {
302  return detail::Reverse<Range>(std::forward<Range>(range));
303 }
304 
305 template<typename Range, typename UnaryOp>
306 [[nodiscard]] auto transform(Range&& range, UnaryOp op)
307 {
308  return detail::Transform<Range, UnaryOp>(std::forward<Range>(range), op);
309 }
310 
311 template<typename Map> [[nodiscard]] auto keys(Map&& map)
312 {
313  return transform(std::forward<Map>(map),
314  [](const auto& t) -> auto& { return std::get<0>(t); });
315 }
316 
317 template<typename Map> [[nodiscard]] auto values(Map&& map)
318 {
319  return transform(std::forward<Map>(map),
320  [](const auto& t) -> auto& { return std::get<1>(t); });
321 }
322 
323 } // namespace view
324 
325 #endif
auto end() const
Definition: view.hh:103
auto transform(Range &&range, UnaryOp op)
Definition: view.hh:306
auto values(Map &&map)
Definition: view.hh:317
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:149
auto rend() const
Definition: view.hh:264
auto begin() const
Definition: view.hh:252
auto rend() const
Definition: view.hh:107
friend TransformIterator operator-(TransformIterator x, difference_type n)
Definition: view.hh:202
friend TransformIterator operator+(difference_type n, TransformIterator x)
Definition: view.hh:196
friend bool operator!=(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:157
Definition: view.hh:10
TransformIterator & operator++()
Definition: view.hh:139
TransformIterator operator++(int)
Definition: view.hh:145
auto begin() const
Definition: view.hh:50
auto begin() const
Definition: view.hh:101
typename std::iterator_traits< Iterator >::iterator_category iterator_category
Definition: view.hh:123
STL namespace.
Drop(Range &&range_, size_t n_)
Definition: view.hh:44
friend bool operator>(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:226
Iterator safe_prev(Iterator first, Iterator last, size_t n, std::bidirectional_iterator_tag)
Definition: view.hh:27
decltype(std::declval< UnaryOp >()(*std::declval< Iterator >())) return_type
Definition: view.hh:118
friend difference_type operator-(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:208
TransformIterator(Iterator it_, UnaryOp op_)
Definition: view.hh:128
friend TransformIterator operator+(TransformIterator x, difference_type n)
Definition: view.hh:191
friend bool operator<=(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:222
TransformIterator & operator--()
Definition: view.hh:164
Definition: join.hh:10
TransformIterator & operator-=(difference_type n)
Definition: view.hh:185
auto size() const
Definition: view.hh:269
auto end() const
Definition: view.hh:80
auto reverse(Range &&range)
Definition: view.hh:300
auto end() const
Definition: view.hh:256
auto keys(Map &&map)
Definition: view.hh:311
return_type operator*() const
Definition: view.hh:135
Iterator safe_next(Iterator first, Iterator last, size_t n, std::input_iterator_tag)
Definition: view.hh:14
auto empty() const
Definition: view.hh:270
TransformIterator & operator+=(difference_type n)
Definition: view.hh:179
DropBack(Range &&range_, size_t n_)
Definition: view.hh:70
auto rbegin() const
Definition: view.hh:105
auto drop_back(Range &&range, size_t n)
Definition: view.hh:294
auto front() const
Definition: view.hh:272
auto end() const
Definition: view.hh:56
friend bool operator<(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:218
Reverse(Range &&range_)
Definition: view.hh:96
auto back() const
Definition: view.hh:273
auto rbegin() const
Definition: view.hh:260
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1377
auto drop(Range &&range, size_t n)
Definition: view.hh:288
typename std::iterator_traits< Iterator >::difference_type difference_type
Definition: view.hh:122
auto begin() const
Definition: view.hh:76
Transform(Range &&range_, UnaryOp op_)
Definition: view.hh:247
friend bool operator>=(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:230
TransformIterator operator--(int)
Definition: view.hh:170
TclObject t
auto operator[](size_t idx) const
Definition: view.hh:275
reference operator[](difference_type n)
Definition: view.hh:213
friend bool operator==(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:152
std::remove_reference_t< return_type > value_type
Definition: view.hh:119