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]] constexpr 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]] constexpr 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]] constexpr 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]] constexpr 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  constexpr Drop(Range&& range_, size_t n_)
45  : range(std::forward<Range>(range_))
46  , n(n_)
47  {
48  }
49 
50  [[nodiscard]] constexpr 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]] constexpr 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  constexpr DropBack(Range&& range_, size_t n_)
71  : range(std::forward<Range>(range_))
72  , n(n_)
73  {
74  }
75 
76  [[nodiscard]] constexpr auto begin() const {
77  return std::begin(range);
78  }
79 
80  [[nodiscard]] constexpr 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  constexpr explicit Reverse(Range&& range_)
97  : range(std::forward<Range>(range_))
98  {
99  }
100 
101  [[nodiscard]] constexpr auto begin() const { return range.rbegin(); }
102  [[nodiscard]] constexpr auto begin() { return range.rbegin(); }
103  [[nodiscard]] constexpr auto end() const { return range.rend(); }
104  [[nodiscard]] constexpr auto end() { return range.rend(); }
105  [[nodiscard]] constexpr auto rbegin() const { return range.begin(); }
106  [[nodiscard]] constexpr auto rbegin() { return range.begin(); }
107  [[nodiscard]] constexpr auto rend() const { return range.end(); }
108  [[nodiscard]] constexpr 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  constexpr TransformIterator() = default;
127 
128  constexpr TransformIterator(Iterator it_, UnaryOp op_)
129  : storage(it_, op_)
130  {
131  }
132 
133  // InputIterator, ForwardIterator
134 
135  [[nodiscard]] constexpr 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]] constexpr friend bool operator==(const TransformIterator& x, const TransformIterator& y)
153  {
154  return x.it() == y.it();
155  }
156 
157  [[nodiscard]] constexpr 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 
191  [[nodiscard]] constexpr friend TransformIterator operator+(TransformIterator x, difference_type n)
192  {
193  x += n;
194  return x;
195  }
196  [[nodiscard]] constexpr friend TransformIterator operator+(difference_type n, TransformIterator x)
197  {
198  x += n;
199  return x;
200  }
201 
202  [[nodiscard]] constexpr friend TransformIterator operator-(TransformIterator x, difference_type n)
203  {
204  x -= n;
205  return x;
206  }
207 
208  [[nodiscard]] constexpr friend difference_type operator-(const TransformIterator& x, const TransformIterator& y)
209  {
210  return x.it() - y.it();
211  }
212 
213  [[nodiscard]] constexpr reference operator[](difference_type n)
214  {
215  return *(*this + n);
216  }
217 
218  [[nodiscard]] constexpr friend bool operator<(const TransformIterator& x, const TransformIterator& y)
219  {
220  return x.it() < y.it();
221  }
222  [[nodiscard]] constexpr friend bool operator<=(const TransformIterator& x, const TransformIterator& y)
223  {
224  return x.it() <= y.it();
225  }
226  [[nodiscard]] constexpr friend bool operator>(const TransformIterator& x, const TransformIterator& y)
227  {
228  return x.it() > y.it();
229  }
230  [[nodiscard]] constexpr 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]] constexpr Iterator& it() { return std::get<0>(storage); }
239  [[nodiscard]] constexpr const Iterator& it() const { return std::get<0>(storage); }
240  [[nodiscard]] constexpr UnaryOp& op() { return std::get<1>(storage); }
241  [[nodiscard]] constexpr const UnaryOp& op() const { return std::get<1>(storage); }
242 };
243 
244 template<typename Range, typename UnaryOp> class Transform
245 {
246 public:
247  constexpr Transform(Range&& range_, UnaryOp op_)
248  : storage(std::forward<Range>(range_), op_)
249  {
250  }
251 
252  [[nodiscard]] constexpr auto begin() const
253  {
254  return TransformIterator(std::begin(range()), op());
255  }
256  [[nodiscard]] constexpr auto end() const
257  {
258  return TransformIterator(std::end(range()), op());
259  }
260  [[nodiscard]] constexpr auto rbegin() const
261  {
262  return TransformIterator(std::rbegin(range()), op());
263  }
264  [[nodiscard]] constexpr auto rend() const
265  {
266  return TransformIterator(std::rend(range()), op());
267  }
268 
269  [[nodiscard]] constexpr auto size() const { return range().size(); }
270  [[nodiscard]] constexpr auto empty() const { return range().empty(); }
271 
272  [[nodiscard]] constexpr auto front() const { return op()(range().front()); }
273  [[nodiscard]] constexpr auto back() const { return op()(range().back()); }
274 
275  [[nodiscard]] constexpr auto operator[](size_t idx) const { return op()(range()[idx]); }
276 
277 private:
278  std::tuple<Range, UnaryOp> storage;
279 
280  [[nodiscard]] constexpr const Range& range() const { return std::get<0>(storage); }
281  [[nodiscard]] constexpr const UnaryOp& op() const { return std::get<1>(storage); }
282 };
283 
284 
285 } // namespace detail
286 
287 template<typename Range>
288 [[nodiscard]] constexpr 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]] constexpr 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]] constexpr auto reverse(Range&& range)
301 {
302  return detail::Reverse<Range>(std::forward<Range>(range));
303 }
304 
305 template<typename Range, typename UnaryOp>
306 [[nodiscard]] constexpr 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]] constexpr 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]] constexpr 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
TclObject t
constexpr DropBack(Range &&range_, size_t n_)
Definition: view.hh:70
constexpr auto begin() const
Definition: view.hh:76
constexpr auto end() const
Definition: view.hh:80
constexpr Drop(Range &&range_, size_t n_)
Definition: view.hh:44
constexpr auto begin() const
Definition: view.hh:50
constexpr auto end() const
Definition: view.hh:56
constexpr auto rend() const
Definition: view.hh:107
constexpr auto end()
Definition: view.hh:104
constexpr auto rend()
Definition: view.hh:108
constexpr auto end() const
Definition: view.hh:103
constexpr auto begin() const
Definition: view.hh:101
constexpr auto rbegin()
Definition: view.hh:106
constexpr auto rbegin() const
Definition: view.hh:105
constexpr auto begin()
Definition: view.hh:102
constexpr Reverse(Range &&range_)
Definition: view.hh:96
constexpr TransformIterator & operator+=(difference_type n)
Definition: view.hh:179
constexpr TransformIterator(Iterator it_, UnaryOp op_)
Definition: view.hh:128
constexpr friend difference_type operator-(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:208
std::remove_reference_t< return_type > value_type
Definition: view.hh:119
constexpr TransformIterator & operator++()
Definition: view.hh:139
constexpr TransformIterator & operator-=(difference_type n)
Definition: view.hh:185
constexpr TransformIterator()=default
constexpr TransformIterator operator++(int)
Definition: view.hh:145
constexpr return_type operator*() const
Definition: view.hh:135
constexpr TransformIterator operator--(int)
Definition: view.hh:170
typename std::iterator_traits< Iterator >::difference_type difference_type
Definition: view.hh:122
typename std::iterator_traits< Iterator >::iterator_category iterator_category
Definition: view.hh:123
constexpr friend bool operator!=(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:157
constexpr friend bool operator>=(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:230
constexpr friend bool operator==(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:152
constexpr friend bool operator<=(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:222
constexpr friend TransformIterator operator+(difference_type n, TransformIterator x)
Definition: view.hh:196
constexpr friend bool operator>(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:226
constexpr friend TransformIterator operator+(TransformIterator x, difference_type n)
Definition: view.hh:191
constexpr friend TransformIterator operator-(TransformIterator x, difference_type n)
Definition: view.hh:202
constexpr friend bool operator<(const TransformIterator &x, const TransformIterator &y)
Definition: view.hh:218
decltype(std::declval< UnaryOp >()(*std::declval< Iterator >())) return_type
Definition: view.hh:118
constexpr reference operator[](difference_type n)
Definition: view.hh:213
constexpr TransformIterator & operator--()
Definition: view.hh:164
constexpr auto operator[](size_t idx) const
Definition: view.hh:275
constexpr auto rbegin() const
Definition: view.hh:260
constexpr auto back() const
Definition: view.hh:273
constexpr auto begin() const
Definition: view.hh:252
constexpr auto empty() const
Definition: view.hh:270
constexpr Transform(Range &&range_, UnaryOp op_)
Definition: view.hh:247
constexpr auto rend() const
Definition: view.hh:264
constexpr auto size() const
Definition: view.hh:269
constexpr auto front() const
Definition: view.hh:272
constexpr auto end() const
Definition: view.hh:256
Definition: join.hh:10
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:124
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:149
constexpr Iterator safe_next(Iterator first, Iterator last, size_t n, std::input_iterator_tag)
Definition: view.hh:14
constexpr Iterator safe_prev(Iterator first, Iterator last, size_t n, std::bidirectional_iterator_tag)
Definition: view.hh:27
Definition: view.hh:10
constexpr auto transform(Range &&range, UnaryOp op)
Definition: view.hh:306
constexpr auto reverse(Range &&range)
Definition: view.hh:300
constexpr auto drop(Range &&range, size_t n)
Definition: view.hh:288
constexpr auto drop_back(Range &&range, size_t n)
Definition: view.hh:294
constexpr auto keys(Map &&map)
Definition: view.hh:311
constexpr auto values(Map &&map)
Definition: view.hh:317
constexpr auto begin(const zstring_view &x)
Definition: zstring_view.hh:82
constexpr auto end(const zstring_view &x)
Definition: zstring_view.hh:83