lxgui
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 
8 namespace lxgui::utils::range {
9 
12 namespace range_impl {
13 
14 template<typename T>
15 struct 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
49 template<typename T>
50 range_impl::reverse_range<T> reverse(T& container) {
51  return range_impl::reverse_range<T>(container);
52 }
53 
56 namespace range_impl {
57 
58 template<typename I>
59 struct 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 
77 template<typename T>
78 struct 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
113 template<typename T>
114 range_impl::iterator_range<T> iterator(T& container) {
115  return range_impl::iterator_range<T>(container);
116 }
117 
120 namespace range_impl {
121 
122 template<typename T>
123 struct 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
158 template<typename T>
159 range_impl::reverse_iterator_range<T> reverse_iterator(T& container) {
160  return range_impl::reverse_iterator_range<T>(container);
161 }
162 
165 namespace range_impl {
166 
167 template<typename I, typename V>
168 struct 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 
186 template<typename T>
187 struct 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
226 template<typename T>
227 range_impl::value_range<T> value(T& container) {
228  return range_impl::value_range<T>(container);
229 }
230 
233 namespace range_impl {
234 
235 template<typename T>
236 struct 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
275 template<typename T>
276 range_impl::reverse_value_range<T> reverse_value(T& container) {
277  return range_impl::reverse_value_range<T>(container);
278 }
279 
282 namespace range_impl {
283 
284 template<typename I, typename K>
285 struct 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 
303 template<typename T>
304 struct 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
340 template<typename T>
341 range_impl::key_range<T> key(T& container) {
342  return range_impl::key_range<T>(container);
343 }
344 
347 namespace range_impl {
348 
349 template<typename T>
350 struct 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
386 template<typename T>
387 range_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::key_range< T > key(T &container)
Expose the key rather than the (key,value) pair.
range_impl::reverse_range< T > reverse(T &container)
Reverse traversal.
Definition: utils_range.hpp:50
range_impl::reverse_iterator_range< T > reverse_iterator(T &container)
Expose the iterator rather than the element, with reverse traversal.
range_impl::iterator_range< T > iterator(T &container)
Expose the iterator rather than the element.
range_impl::reverse_key_range< T > reverse_key(T &container)
Expose the key rather than the (key,value) pair, with reverse traversal.
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.