Photon microGUI widgets library 0.6.0
iterator.hpp
1#ifndef _STDEX_ITERATOR_H
2#define _STDEX_ITERATOR_H
3
4#if _MSC_VER > 1000
5#pragma once
6#endif // _MSC_VER > 1000
7
8// stdex includes
9
10// POSIX includes
11
12// std includes
13#include <iterator>
14#include <cstddef> //cstddef::size_t
15
16#ifdef _STDEX_NATIVE_CPP11_SUPPORT
17
18#define _STDEX_DELETED_FUNCTION =delete
19#define _STDEX_NOEXCEPT_FUNCTION noexcept
20
21#else
22
23#define _STDEX_DELETED_FUNCTION
24#define _STDEX_NOEXCEPT_FUNCTION throw()
25
26#endif
27
28namespace stdex
29{
30 namespace iterator_cpp11
31 {
32#ifndef STDEX_DO_NOT_ADD_CPP11_STD // define to exclude std implementations
33 using namespace std;
34#endif
35 }
36
37 namespace cstddef
38 {
39 typedef std::size_t size_t;
40 }
41
42 // Iterator primitives
43
44 using std::iterator_traits; // provides uniform interface to the properties of an iterator
45 // (class template)
46 using std::input_iterator_tag;
47 using std::output_iterator_tag;
48 using std::forward_iterator_tag;
49 using std::bidirectional_iterator_tag;
50 using std::random_access_iterator_tag;
51
52 using std::iterator; // base class to ease the definition of required types for simple iterators
53 // (class template)
54
55 //Iterator adaptors
56
57 using std::reverse_iterator; // iterator adaptor for reverse-order traversal
58 // (class template)
59 //<TODO>: using std::make_reverse_iterator; // (C++14)
60 // creates a std::reverse_iterator of type inferred from the argument
61 // (function template)
62 //using std::move_iterator; // (C++11)
63 // iterator adaptor which dereferences to an rvalue reference
64 // (class template)
65 //using std::make_move_iterator; // (C++11)
66 // creates a std::move_iterator of type inferred from the argument
67 // (function template)
68 using std::back_insert_iterator; // iterator adaptor for insertion at the end of a container
69 // (class template)
70 using std::back_inserter; // creates a std::back_insert_iterator of type inferred from the argument
71 // (function template)
72 using std::front_insert_iterator; // iterator adaptor for insertion at the front of a container
73 // (class template)
74 using std::front_inserter; // creates a std::front_insert_iterator of type inferred from the argument
75 // (function template)
76 using std::insert_iterator; // iterator adaptor for insertion into a container
77 // (class template)
78 using std::inserter; // creates a std::insert_iterator of type inferred from the argument
79 // (function template)
80
81 // Stream iterators
82
83 using std::istream_iterator; // input iterator that reads from std::basic_istream
84 // (class template)
85 using std::ostream_iterator; // output iterator that writes to std::basic_ostream
86 // (class template)
87 using std::istreambuf_iterator; // input iterator that reads from std::basic_streambuf
88 // (class template)
89 using std::ostreambuf_iterator; // output iterator that writes to std::basic_streambuf
90 // (class template)
91
92 // Iterator operations
93
94 using std::advance; // advances an iterator by given distance
95 // (function)
96 using std::distance; // returns the distance between two iterators
97 // (function)
98
99 namespace detail
100 {
101 struct _iterator_false_type { static const bool value = false; };
102 struct _iterator_true_type { static const bool value = true; };
103
104 template <bool, class _Tp>
105 struct _iterator_enable_if
106 {
107 private:
108 struct _iterator_enable_if_dummy;
109 public:
110 typedef _iterator_enable_if_dummy(&type)[1];
111 };
112
113 template <class _Tp>
114 struct _iterator_enable_if<true, _Tp>
115 {
116 typedef _Tp type;
117 };
118
119 template<class, class>
120 struct _iterator_is_same:
121 _iterator_false_type
122 { };
123
124 template<class _Tp>
125 struct _iterator_is_same<_Tp, _Tp>:
126 _iterator_true_type
127 { };
128
129 template<class>
130 struct _iterator_is_reference:
131 _iterator_false_type
132 { };
133
134 template<class _Tp>
135 struct _iterator_is_reference<_Tp&> :
136 _iterator_true_type
137 { };
138
139 template<class>
140 struct _iterator_is_not_void :
141 _iterator_true_type
142 { };
143
144 template<>
145 struct _iterator_is_not_void<void> :
146 _iterator_false_type
147 { };
148
149 template<bool, class _ItType>
150 struct _iterator_traits_enable_if
151 {
152 typedef _iterator_enable_if<false, void>::type type;
153 typedef _iterator_enable_if<false, void>::type iterator_category;
154 typedef _iterator_enable_if<false, void>::type value_type;
155 typedef _iterator_enable_if<false, void>::type difference_type;
156 typedef _iterator_enable_if<false, void>::type pointer;
157 typedef _iterator_enable_if<false, void>::type reference;
158 };
159
160 template<class _ItType>
161 struct _iterator_traits_enable_if<true, _ItType>:
162 std::iterator_traits<_ItType>,
163 _iterator_enable_if<true, _ItType>
164 { };
165
166 typedef char _iterator_yes_type;
167 struct _iterator_no_type
168 {
169 char padding[8];
170 };
171
172 _iterator_yes_type _input_iterator_cat_tester(std::input_iterator_tag*);
173 _iterator_no_type _input_iterator_cat_tester(...);
174 _iterator_yes_type _output_iterator_cat_tester(std::output_iterator_tag*);
175 _iterator_no_type _output_iterator_cat_tester(...);
176 _iterator_yes_type _forward_iterator_cat_tester(std::forward_iterator_tag*);
177 _iterator_no_type _forward_iterator_cat_tester(...);
178 _iterator_yes_type _bidirectional_iterator_cat_tester(std::bidirectional_iterator_tag*);
179 _iterator_no_type _bidirectional_iterator_cat_tester(...);
180 _iterator_yes_type _random_access_iterator_cat_tester(std::random_access_iterator_tag*);
181 _iterator_no_type _random_access_iterator_cat_tester(...);
182
183 template<class _ItCategory, class>
184 struct _iterator_cat_is;
185
186 template<class _ItCategory>
187 struct _iterator_cat_is<_ItCategory, std::input_iterator_tag>
188 {
189 static const bool value = sizeof(_input_iterator_cat_tester((_ItCategory*)(0))) == sizeof(_iterator_yes_type);
190 };
191
192 template<class _ItCategory>
193 struct _iterator_cat_is<_ItCategory, std::output_iterator_tag>
194 {
195 static const bool value = sizeof(_output_iterator_cat_tester((_ItCategory*)(0))) == sizeof(_iterator_yes_type);
196 };
197
198 template<class _ItCategory>
199 struct _iterator_cat_is<_ItCategory, std::forward_iterator_tag>
200 {
201 static const bool value = sizeof(_forward_iterator_cat_tester((_ItCategory*)(0))) == sizeof(_iterator_yes_type);
202 };
203
204 template<class _ItCategory>
205 struct _iterator_cat_is<_ItCategory, std::bidirectional_iterator_tag>
206 {
207 static const bool value = sizeof(_bidirectional_iterator_cat_tester((_ItCategory*)(0))) == sizeof(_iterator_yes_type);
208 };
209
210 template<class _ItCategory>
211 struct _iterator_cat_is<_ItCategory, std::random_access_iterator_tag>
212 {
213 static const bool value = sizeof(_random_access_iterator_cat_tester((_ItCategory*)(0))) == sizeof(_iterator_yes_type);
214 };
215
216 template<class _ItCategory, class _CheckCategory>
217 struct _iterator_cat_is_valid:
218 _iterator_cat_is<_ItCategory, _CheckCategory>
219 { };
220
221 template<class _ItCategory>
222 struct _iterator_cat_is_valid<_ItCategory, std::output_iterator_tag>
223 {
224 static const bool value =
225 _iterator_cat_is<_ItCategory, std::forward_iterator_tag>::value ||
226 _iterator_cat_is<_ItCategory, std::output_iterator_tag>::value;
227 };
228
229 template<class _InputIt>
230 struct _if_iterator_cat_is_input:
231 _iterator_traits_enable_if<
232 _iterator_cat_is<
233 typename std::iterator_traits<_InputIt>::iterator_category,
234 std::input_iterator_tag
235 >::value == bool(true),
236 _InputIt
237 >
238 {};
239
240 template<class _OutputIt>
241 struct _if_iterator_is_valid_output:
242 _iterator_traits_enable_if<
243 _iterator_cat_is_valid<
244 typename std::iterator_traits<_OutputIt>::iterator_category,
245 std::output_iterator_tag
246 >::value == bool(true),
247 _OutputIt
248 >
249 {};
250
251 template<class _ForwardIt>
252 struct _if_iterator_cat_is_forward:
253 _iterator_traits_enable_if<
254 _iterator_cat_is<
255 typename std::iterator_traits<_ForwardIt>::iterator_category,
256 std::forward_iterator_tag
257 >::value == bool(true),
258 _ForwardIt
259 >
260 {};
261
262 template<class _BidirIt>
263 struct _if_iterator_cat_is_bi:
264 _iterator_traits_enable_if<
265 _iterator_cat_is<
266 typename std::iterator_traits<_BidirIt>::iterator_category,
267 std::bidirectional_iterator_tag
268 >::value == bool(true),
269 _BidirIt
270 >
271 {};
272
273 template<class _RandomIt>
274 struct _if_iterator_cat_is_rand_access:
275 _if_iterator_cat_is_bi<_RandomIt>
276 {};
277 } // namespace detail
278
279 namespace detail
280 {
281 // some iterator traits
282
283 template<class _It>
284 struct _is_legacy_iterator:
285 _iterator_is_not_void<
286 typename std::iterator_traits<_It>::reference>
287 { };
288
289 template<class _It, bool>
290 struct _is_legacy_input_iterator_impl :
291 _iterator_false_type { };
292
293 template<class _It>
294 struct _is_legacy_input_iterator_impl<_It, true> :
295 _iterator_cat_is_valid<_It, std::input_iterator_tag>
296 { };
297
298 template<class _It>
299 struct _is_legacy_input_iterator:
300 _is_legacy_input_iterator_impl<_It, _is_legacy_iterator<_It>::value>
301 { };
302
303 template<class _It, bool>
304 struct _is_legacy_forward_iterator_impl :
305 _iterator_false_type { };
306
307 template<class _It>
308 struct _is_legacy_forward_iterator_impl<_It, true> :
309 _iterator_cat_is_valid<_It, std::forward_iterator_tag>
310 { };
311
312 template<class _It>
313 struct _is_legacy_forward_iterator :
314 _is_legacy_forward_iterator_impl<_It, _is_legacy_input_iterator<_It>::value>
315 { };
316
317 template<class _It, bool>
318 struct _is_legacy_bi_iterator_impl :
319 _iterator_false_type { };
320
321 template<class _It>
322 struct _is_legacy_bi_iterator_impl<_It, true> :
323 _iterator_cat_is_valid<_It, std::bidirectional_iterator_tag>
324 { };
325
326 template<class _It>
327 struct _is_legacy_bi_iterator :
328 _is_legacy_bi_iterator_impl<_It, _is_legacy_forward_iterator<_It>::value>
329 { };
330
331 template<class _It, bool>
332 struct _is_legacy_rand_iterator_impl :
333 _iterator_false_type { };
334
335 template<class _It>
336 struct _is_legacy_rand_iterator_impl<_It, true> :
337 _iterator_cat_is_valid<_It, std::random_access_iterator_tag>
338 { };
339
340 template<class _It>
341 struct _is_legacy_rand_iterator :
342 _is_legacy_rand_iterator_impl<_It, _is_legacy_bi_iterator<_It>::value>
343 { };
344 } // namespace detail
345
346 namespace iterator_cpp11
347 {
348 // next (C++11)
349 // increment an iterator
350 template<class _ForwardIt>
351 inline
352 _ForwardIt next(_ForwardIt _it,
353 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::difference_type _n)
354 {
355 std::advance(_it, _n);
356 return _it;
357 }
358
359 // next (C++11)
360 // increment an iterator by one
361 template<class _ForwardIt>
362 inline
363 _ForwardIt next(_ForwardIt _it)
364 {
365 return iterator_cpp11::next(_it, 1);
366 }
367
368 // prev (C++11)
369 // decrement an iterator
370 template<class _BidirIt>
371 inline
372 _BidirIt prev(_BidirIt _it,
373 typename detail::_if_iterator_cat_is_bi<_BidirIt>::difference_type _n)
374 {
375 std::advance(_it, -_n);
376 return _it;
377 }
378
379 // prev (C++11)
380 // decrement an iterator by 1
381 template<class _BidirIt>
382 inline
383 _BidirIt prev(_BidirIt _it)
384 {
385 return iterator_cpp11::prev(_it, 1);
386 }
387 } // namespace iterator_cpp11
388
389 // next (C++11)
390 // increment an iterator
391 using iterator_cpp11::next;
392
393 // prev (C++11)
394 // decrement an iterator
395 using iterator_cpp11::prev;
396
397 // Range access
398
399 namespace iterator_cpp11
400 {
401 // begin (C++11)
402 // returns an iterator to the beginning of a container or array
403 template<class _ContainerType>
404 inline
405 typename _ContainerType::iterator begin(_ContainerType &value)
406 { // get beginning of sequence
407 return (value.begin());
408 }
409
410 // begin (C++11)
411 // returns an iterator to the beginning of a container or array
412 template<class _ContainerType>
413 inline
414 typename _ContainerType::const_iterator begin(const _ContainerType &value)
415 { // get beginning of sequence
416 return (value.begin());
417 }
418
419 // begin (C++11)
420 // returns an iterator to the beginning of a container or array
421 template<class _Tp, cstddef::size_t Size>
422 inline
423 _Tp* begin(_Tp(&value)[Size]) _STDEX_NOEXCEPT_FUNCTION
424 { // get beginning of array
425 return (value);
426 }
427
428 // begin (C++11)
429 // returns an iterator to the beginning of a container or array
430 template<class _Tp, cstddef::size_t Size>
431 inline
432 const _Tp* begin(const _Tp(&value)[Size]) _STDEX_NOEXCEPT_FUNCTION
433 { // get beginning of array
434 return (value);
435 }
436
437 // end (C++11)
438 // returns an iterator to the end of a container or array
439 template<class _ContainerType>
440 inline
441 typename _ContainerType::iterator end(_ContainerType &value)
442 { // get end of sequence
443 return (value.end());
444 }
445
446 // end (C++11)
447 // returns an iterator to the end of a container or array
448 template<class _ContainerType>
449 inline
450 typename _ContainerType::const_iterator end(const _ContainerType &value)
451 { // get end of sequence
452 return (value.end());
453 }
454
455 // end (C++11)
456 // returns an iterator to the end of a container or array
457 template<class _Tp, cstddef::size_t Size>
458 inline
459 _Tp* end(_Tp(&value)[Size]) _STDEX_NOEXCEPT_FUNCTION
460 { // get end of array
461 return (value + Size);
462 }
463
464 // end (C++11)
465 // returns an iterator to the end of a container or array
466 template<class _Tp, cstddef::size_t Size>
467 inline
468 const _Tp* end(const _Tp(&value)[Size]) _STDEX_NOEXCEPT_FUNCTION
469 { // get end of array
470 return (value + Size);
471 }
472 } // namespace iterator_cpp11
473
474 // begin (C++11)
475 // returns an iterator to the beginning of a container or array
476 using iterator_cpp11::begin;
477
478
479
480 // end (C++11)
481 // returns an iterator to the end of a container or array
482 using iterator_cpp11::end;
483
484 // Container access (C++ 17)
485} // namespace stdex
486
487#undef _STDEX_DELETED_FUNCTION
488#undef _STDEX_NOEXCEPT_FUNCTION
489
490#endif // _STDEX_ITERATOR_H