lxgui
Loading...
Searching...
No Matches
utils_range.hpp
1#ifndef LXGUI_UTILS_RANGE_HPP
2#define LXGUI_UTILS_RANGE_HPP
3
4#include "lxgui/lxgui.hpp"
5
6#include <type_traits>
7
9
12namespace range_impl {
13
14template<typename T>
15struct reverse_range {
16 using base = typename std::decay<T>::type;
17 using iterator = typename std::conditional<
18 std::is_const<T>::value,
19 typename base::const_reverse_iterator,
20 typename base::reverse_iterator>::type;
21
22 T& container;
23
24 explicit reverse_range(T& c) : container(c) {}
25
26 iterator begin() {
27 return iterator(container.rbegin());
28 }
29 iterator end() {
30 return iterator(container.rend());
31 }
32};
33
34} // namespace range_impl
49template<typename T>
50range_impl::reverse_range<T> reverse(T& container) {
51 return range_impl::reverse_range<T>(container);
52}
53
56namespace range_impl {
57
58template<typename I>
59struct iterator_adapter {
60 I iter;
61 explicit iterator_adapter(I i) : iter(i) {}
62 I operator*() {
63 return iter;
64 }
65 iterator_adapter& operator++() {
66 ++iter;
67 return *this;
68 }
69 iterator_adapter operator++(int) {
70 return iter++;
71 }
72 bool operator!=(const iterator_adapter& o) {
73 return iter != o.iter;
74 }
75};
76
77template<typename T>
78struct iterator_range {
79 using base = typename std::decay<T>::type;
80 using base_iterator = typename std::conditional<
81 std::is_const<T>::value,
82 typename base::const_iterator,
83 typename base::iterator>::type;
84 using iterator = iterator_adapter<base_iterator>;
85
86 T& container;
87
88 explicit iterator_range(T& c) : container(c) {}
89
90 iterator begin() {
91 return iterator(container.begin());
92 }
93 iterator end() {
94 return iterator(container.end());
95 }
96};
97
98} // namespace range_impl
113template<typename T>
114range_impl::iterator_range<T> iterator(T& container) {
115 return range_impl::iterator_range<T>(container);
116}
117
120namespace range_impl {
121
122template<typename T>
123struct reverse_iterator_range {
124 using base = typename std::decay<T>::type;
125 using base_iterator = typename std::conditional<
126 std::is_const<T>::value,
127 typename base::const_reverse_iterator,
128 typename base::reverse_iterator>::type;
129 using iterator = iterator_adapter<base_iterator>;
130
131 T& container;
132
133 explicit reverse_iterator_range(T& c) : container(c) {}
134
135 iterator begin() {
136 return iterator(container.rbegin());
137 }
138 iterator end() {
139 return iterator(container.rend());
140 }
141};
142
143} // namespace range_impl
158template<typename T>
159range_impl::reverse_iterator_range<T> reverse_iterator(T& container) {
160 return range_impl::reverse_iterator_range<T>(container);
161}
162
165namespace range_impl {
166
167template<typename I, typename V>
168struct value_iterator_adapter {
169 I iter;
170 explicit value_iterator_adapter(I i) : iter(i) {}
171 V& operator*() {
172 return iter->second;
173 }
174 value_iterator_adapter& operator++() {
175 ++iter;
176 return *this;
177 }
178 value_iterator_adapter operator++(int) {
179 return iter++;
180 }
181 bool operator!=(const value_iterator_adapter& o) {
182 return iter != o.iter;
183 }
184};
185
186template<typename T>
187struct value_range {
188 using base = typename std::decay<T>::type;
189 using base_iterator = typename std::conditional<
190 std::is_const<T>::value,
191 typename base::const_iterator,
192 typename base::iterator>::type;
193 using value_type = typename std::conditional<
194 std::is_const<T>::value,
195 const typename base::mapped_type,
196 typename base::mapped_type>::type;
197 using iterator = value_iterator_adapter<base_iterator, value_type>;
198
199 T& container;
200
201 explicit value_range(T& c) : container(c) {}
202
203 iterator begin() {
204 return iterator(container.begin());
205 }
206 iterator end() {
207 return iterator(container.end());
208 }
209};
210
211} // namespace range_impl
226template<typename T>
227range_impl::value_range<T> value(T& container) {
228 return range_impl::value_range<T>(container);
229}
230
233namespace range_impl {
234
235template<typename T>
236struct reverse_value_range {
237 using base = typename std::decay<T>::type;
238 using base_iterator = typename std::conditional<
239 std::is_const<T>::value,
240 typename base::const_reverse_iterator,
241 typename base::reverse_iterator>::type;
242 using value_type = typename std::conditional<
243 std::is_const<T>::value,
244 const typename base::mapped_type,
245 typename base::mapped_type>::type;
246 using iterator = value_iterator_adapter<base_iterator, value_type>;
247
248 T& container;
249
250 explicit reverse_value_range(T& c) : container(c) {}
251
252 iterator begin() {
253 return iterator(container.rbegin());
254 }
255 iterator end() {
256 return iterator(container.rend());
257 }
258};
259
260} // namespace range_impl
275template<typename T>
276range_impl::reverse_value_range<T> reverse_value(T& container) {
277 return range_impl::reverse_value_range<T>(container);
278}
279
282namespace range_impl {
283
284template<typename I, typename K>
285struct key_iterator_adapter {
286 I iter;
287 explicit key_iterator_adapter(I i) : iter(i) {}
288 const K& operator*() {
289 return iter->first;
290 }
291 key_iterator_adapter& operator++() {
292 ++iter;
293 return *this;
294 }
295 key_iterator_adapter operator++(int) {
296 return iter++;
297 }
298 bool operator!=(const key_iterator_adapter& o) {
299 return iter != o.iter;
300 }
301};
302
303template<typename T>
304struct key_range {
305 using base = typename std::decay<T>::type;
306 using base_iterator = typename std::conditional<
307 std::is_const<T>::value,
308 typename base::const_iterator,
309 typename base::iterator>::type;
310 using key_type = typename base::key_type;
311 using iterator = key_iterator_adapter<base_iterator, key_type>;
312
313 T& container;
314
315 explicit key_range(T& c) : container(c) {}
316
317 iterator begin() {
318 return iterator(container.begin());
319 }
320 iterator end() {
321 return iterator(container.end());
322 }
323};
324
325} // namespace range_impl
340template<typename T>
341range_impl::key_range<T> key(T& container) {
342 return range_impl::key_range<T>(container);
343}
344
347namespace range_impl {
348
349template<typename T>
350struct reverse_key_range {
351 using base = typename std::decay<T>::type;
352 using base_iterator = typename std::conditional<
353 std::is_const<T>::value,
354 typename base::const_reverse_iterator,
355 typename base::reverse_iterator>::type;
356 using key_type = typename base::key_type;
357 using iterator = key_iterator_adapter<base_iterator, key_type>;
358
359 T& container;
360
361 explicit reverse_key_range(T& c) : container(c) {}
362
363 iterator begin() {
364 return iterator(container.rbegin());
365 }
366 iterator end() {
367 return iterator(container.rend());
368 }
369};
370
371} // namespace range_impl
386template<typename T>
387range_impl::reverse_key_range<T> reverse_key(T& container) {
388 return range_impl::reverse_key_range<T>(container);
389}
390
391} // namespace lxgui::utils::range
392
393#endif
range_impl::reverse_iterator_range< T > reverse_iterator(T &container)
Expose the iterator rather than the element, with reverse traversal.
range_impl::reverse_range< T > reverse(T &container)
Reverse traversal.
range_impl::key_range< T > key(T &container)
Expose the key rather than the (key,value) pair.
range_impl::value_range< T > value(T &container)
Expose the value rather than the (key,value) pair.
range_impl::reverse_value_range< T > reverse_value(T &container)
Expose the value rather than the (key,value) pair, with reverse traversal.
range_impl::reverse_key_range< T > reverse_key(T &container)
Expose the key rather than the (key,value) pair, with reverse traversal.
range_impl::iterator_range< T > iterator(T &container)
Expose the iterator rather than the element.