Embedded Template Library 1.0
Loading...
Searching...
No Matches
iterator.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2017 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_ITERATOR_INCLUDED
32#define ETL_ITERATOR_INCLUDED
33
34#include "platform.h"
35#include "invoke.h"
36#include "type_traits.h"
37#include "utility.h"
38#include "private/addressof.h"
39
40#if ETL_USING_STL || defined(ETL_IN_UNIT_TEST)
41 #include <iterator>
42#endif
43
46
47namespace etl
48{
49 //***************************************************************************
50 // iterator tags
52 {
53 };
55 {
56 };
58 {
59 };
66 // struct contiguous_iterator_tag : public random_access_iterator_tag {};
67
68 //***************************************************************************
69 // iterator_traits
70
71#if ETL_USING_CPP11
72
73 // Primary template: falls through to std::iterator_traits when STL is available (C++20+),
74 // otherwise empty (SFINAE-safe fallback for iterators without nested typedefs).
75 template <typename TIterator, typename = void>
76 struct iterator_traits
77 #if ETL_USING_STL && ETL_USING_CPP20
78 : std::iterator_traits<TIterator>
79 #endif
80 {
81 };
82
83 // Specialization for iterators that define the standard nested typedefs.
84 template <typename TIterator>
85 struct iterator_traits<TIterator, etl::void_t< typename TIterator::iterator_category, typename TIterator::value_type,
86 typename TIterator::difference_type, typename TIterator::pointer, typename TIterator::reference >>
87 {
88 typedef typename TIterator::iterator_category iterator_category;
89 typedef typename TIterator::value_type value_type;
90 typedef typename TIterator::difference_type difference_type;
91 typedef typename TIterator::pointer pointer;
92 typedef typename TIterator::reference reference;
93 };
94
95 #if ETL_USING_STL && ETL_USING_CPP20
96 // Specialization for std::common_iterator (C++20).
97 template <typename I, typename S>
98 struct iterator_traits<std::common_iterator<I, S>, void> : std::iterator_traits<std::common_iterator<I, S>>
99 {
100 };
101 #endif
102
103 // For pointers.
104 template <typename T>
105 struct iterator_traits<T*, void>
106 {
107 typedef ETL_OR_STD::random_access_iterator_tag iterator_category;
108 typedef T value_type;
109 typedef ptrdiff_t difference_type;
110 typedef typename etl::remove_cv<T>::type* pointer;
111 typedef T& reference;
112 };
113
114 // For const pointers.
115 template <typename T>
116 struct iterator_traits<const T*, void>
117 {
118 typedef ETL_OR_STD::random_access_iterator_tag iterator_category;
119 typedef T value_type;
120 typedef ptrdiff_t difference_type;
121 typedef const typename etl::remove_cv<T>::type* pointer;
122 typedef const T& reference;
123 };
124
125#else // C++03
126
127 // Primary template: unconditionally extracts nested typedefs.
128 template <typename TIterator>
130 {
131 typedef typename TIterator::iterator_category iterator_category;
132 typedef typename TIterator::value_type value_type;
133 typedef typename TIterator::difference_type difference_type;
134 typedef typename TIterator::pointer pointer;
135 typedef typename TIterator::reference reference;
136 };
137
138 // For pointers.
139 template <typename T>
141 {
142 typedef ETL_OR_STD::random_access_iterator_tag iterator_category;
143 typedef T value_type;
144 typedef ptrdiff_t difference_type;
145 typedef typename etl::remove_cv<T>::type* pointer;
146 typedef T& reference;
147 };
148
149 // For const pointers.
150 template <typename T>
151 struct iterator_traits<const T*>
152 {
153 typedef ETL_OR_STD::random_access_iterator_tag iterator_category;
154 typedef T value_type;
155 typedef ptrdiff_t difference_type;
156 typedef const typename etl::remove_cv<T>::type* pointer;
157 typedef const T& reference;
158 };
159
160#endif
161
162 //***************************************************************************
163 // advance
164 template <typename TIterator, typename TDistance>
165 ETL_CONSTEXPR14 void advance_helper(TIterator& itr, TDistance n, ETL_OR_STD::input_iterator_tag)
166 {
167 while (n-- > 0)
168 {
169 ++itr;
170 }
171 }
172
173 template <typename TIterator, typename TDistance>
174 ETL_CONSTEXPR14 void advance_helper(TIterator& itr, TDistance n, ETL_OR_STD::output_iterator_tag)
175 {
176 while (n-- > 0)
177 {
178 ++itr;
179 }
180 }
181
182 template <typename TIterator, typename TDistance>
183 ETL_CONSTEXPR14 void advance_helper(TIterator& itr, TDistance n, ETL_OR_STD::forward_iterator_tag)
184 {
185 while (n-- > 0)
186 {
187 ++itr;
188 }
189 }
190
191 template <typename TIterator, typename TDistance>
192 ETL_CONSTEXPR14 void advance_helper(TIterator& itr, TDistance n, ETL_OR_STD::bidirectional_iterator_tag)
193 {
194 if (n > 0)
195 {
196 while (n--)
197 {
198 ++itr;
199 }
200 }
201 else
202 {
203 while (n++)
204 {
205 --itr;
206 }
207 }
208 }
209
210 template <typename TIterator, typename TDistance>
211 ETL_CONSTEXPR14 void advance_helper(TIterator& itr, TDistance n, ETL_OR_STD::random_access_iterator_tag)
212 {
213 typedef typename etl::iterator_traits<TIterator>::difference_type diff_t;
214 itr += static_cast<diff_t>(n);
215 }
216
217 template <typename TIterator, typename TDistance>
218 ETL_CONSTEXPR14 void advance(TIterator& itr, TDistance n)
219 {
220 typedef typename etl::iterator_traits<TIterator>::iterator_category tag;
221
222 advance_helper(itr, n, tag());
223 }
224
225 //***************************************************************************
226 // distance
227 template <typename TIterator>
228 ETL_CONSTEXPR14 typename etl::iterator_traits<TIterator>::difference_type distance_helper(TIterator first, TIterator last, ETL_OR_STD::input_iterator_tag)
229 {
230 typename etl::iterator_traits<TIterator>::difference_type d = 0;
231
232 while (first != last)
233 {
234 ++d;
235 ++first;
236 }
237
238 return d;
239 }
240
241 template <typename TIterator>
242 ETL_CONSTEXPR14 typename etl::iterator_traits<TIterator>::difference_type distance_helper(TIterator first, TIterator last,
243 ETL_OR_STD::forward_iterator_tag)
244 {
245 typename etl::iterator_traits<TIterator>::difference_type d = 0;
246
247 while (first != last)
248 {
249 ++d;
250 ++first;
251 }
252
253 return d;
254 }
255
256 template <typename TIterator>
257 ETL_CONSTEXPR14 typename etl::iterator_traits<TIterator>::difference_type distance_helper(TIterator first, TIterator last,
258 ETL_OR_STD::bidirectional_iterator_tag)
259 {
260 typename etl::iterator_traits<TIterator>::difference_type d = 0;
261
262 while (first != last)
263 {
264 ++d;
265 ++first;
266 }
267
268 return d;
269 }
270
271 template <typename TIterator>
272 ETL_CONSTEXPR14 typename etl::iterator_traits<TIterator>::difference_type distance_helper(TIterator first, TIterator last,
273 ETL_OR_STD::random_access_iterator_tag)
274 {
275 return last - first;
276 }
277
278 template <typename TIterator>
279 ETL_CONSTEXPR14 typename etl::iterator_traits<TIterator>::difference_type distance(TIterator first, TIterator last)
280 {
281 typedef typename etl::iterator_traits<TIterator>::iterator_category tag;
282
283 return distance_helper(first, last, tag());
284 }
285
286 //***************************************************************************
287 // Previous
288 template <typename TIterator>
289 ETL_CONSTEXPR14 TIterator prev(TIterator itr, typename etl::iterator_traits<TIterator>::difference_type n = 1)
290 {
291 etl::advance(itr, -n);
292
293 return itr;
294 }
295
296 //***************************************************************************
297 // Next
298 template <typename TIterator>
299 ETL_CONSTEXPR14 TIterator next(TIterator itr, typename etl::iterator_traits<TIterator>::difference_type n = 1)
300 {
301 etl::advance(itr, n);
302
303 return itr;
304 }
305
306 //***************************************************************************
307 // reverse_iterator
308 template <typename TIterator>
309 class reverse_iterator
310 {
311 public:
312
313 typedef typename iterator_traits<TIterator>::iterator_category iterator_category;
314 typedef typename iterator_traits<TIterator>::value_type value_type;
315 typedef typename iterator_traits<TIterator>::difference_type difference_type;
316 typedef typename iterator_traits<TIterator>::pointer pointer;
317 typedef typename iterator_traits<TIterator>::reference reference;
318
319 typedef TIterator iterator_type;
320
321 ETL_CONSTEXPR14 reverse_iterator()
322 : current()
323 {
324 }
325
326 ETL_CONSTEXPR14 explicit reverse_iterator(TIterator itr)
327 : current(itr)
328 {
329 }
330
331 template <typename TOther>
332 ETL_CONSTEXPR14 reverse_iterator(const reverse_iterator<TOther>& other)
333 : current(other.base())
334 {
335 }
336
337 template <class TOther>
338 ETL_CONSTEXPR14 reverse_iterator& operator=(const reverse_iterator<TOther>& other)
339 {
340 current = other.base();
341
342 return (*this);
343 }
344
345 ETL_CONSTEXPR14 TIterator base() const
346 {
347 return current;
348 }
349
350 ETL_NODISCARD ETL_CONSTEXPR14 reference operator*() const
351 {
352 TIterator temp = current;
353
354 return *(--temp);
355 }
356
357 ETL_NODISCARD ETL_CONSTEXPR14 pointer operator->() const
358 {
359 TIterator temp = current;
360
361 return &(*--temp);
362 }
363
364 ETL_CONSTEXPR14 reverse_iterator& operator++()
365 {
366 --current;
367
368 return *this;
369 }
370
371 ETL_CONSTEXPR14 reverse_iterator operator++(int)
372 {
373 reverse_iterator temp = *this;
374 --current;
375
376 return temp;
377 }
378
379 ETL_CONSTEXPR14 reverse_iterator& operator--()
380 {
381 ++current;
382
383 return (*this);
384 }
385
386 ETL_CONSTEXPR14 reverse_iterator operator--(int)
387 {
388 reverse_iterator temp = *this;
389 ++current;
390
391 return temp;
392 }
393
394 ETL_CONSTEXPR14 reverse_iterator& operator+=(const difference_type offset)
395 {
396 current -= offset;
397
398 return (*this);
399 }
400
401 ETL_CONSTEXPR14 reverse_iterator& operator-=(const difference_type offset)
402 {
403 current += offset;
404
405 return (*this);
406 }
407
408 ETL_NODISCARD ETL_CONSTEXPR14 reverse_iterator operator+(const difference_type offset) const
409 {
410 return reverse_iterator(current - offset);
411 }
412
413 ETL_NODISCARD ETL_CONSTEXPR14 reverse_iterator operator-(const difference_type offset) const
414 {
415 return (reverse_iterator(current + offset));
416 }
417
418 ETL_NODISCARD ETL_CONSTEXPR14 reference operator[](const difference_type offset) const
419 {
420 return (*(*this + offset));
421 }
422
423 protected:
424
425 TIterator current;
426 };
427
428 template <typename TIterator>
429 ETL_CONSTEXPR14 bool operator==(const reverse_iterator<TIterator>& lhs, const reverse_iterator<TIterator>& rhs)
430 {
431 return lhs.base() == rhs.base();
432 }
433
434 template <typename TIterator>
435 ETL_CONSTEXPR14 bool operator!=(const reverse_iterator<TIterator>& lhs, const reverse_iterator<TIterator>& rhs)
436 {
437 return !(lhs == rhs);
438 }
439
440 template <typename TIterator>
441 ETL_CONSTEXPR14 bool operator<(const reverse_iterator<TIterator>& lhs, const reverse_iterator<TIterator>& rhs)
442 {
443 return rhs.base() < lhs.base();
444 }
445
446 template <typename TIterator>
447 ETL_CONSTEXPR14 bool operator>(const reverse_iterator<TIterator>& lhs, const reverse_iterator<TIterator>& rhs)
448 {
449 return rhs < lhs;
450 }
451
452 template <typename TIterator>
453 ETL_CONSTEXPR14 bool operator<=(const reverse_iterator<TIterator>& lhs, const reverse_iterator<TIterator>& rhs)
454 {
455 return !(rhs < lhs);
456 }
457
458 template <typename TIterator>
459 ETL_CONSTEXPR14 bool operator>=(const reverse_iterator<TIterator>& lhs, const reverse_iterator<TIterator>& rhs)
460 {
461 return !(lhs < rhs);
462 }
463
464 template <typename TIterator>
465 ETL_CONSTEXPR14 typename reverse_iterator<TIterator>::difference_type operator-(const reverse_iterator<TIterator>& lhs,
467 {
468 return rhs.base() - lhs.base();
469 }
470
471 template <typename TIterator, class TDifference>
472 ETL_CONSTEXPR14 reverse_iterator<TIterator> operator+(TDifference n, const reverse_iterator<TIterator>& itr)
473 {
474 return itr.operator+(n);
475 }
476
477 //***************************************************************************
479 //***************************************************************************
480 template <typename TCategory, typename T, typename TDistance = ptrdiff_t, typename TPointer = T*, typename TReference = T& >
481 struct iterator
482 {
483 typedef T value_type;
484 typedef TDistance difference_type;
485 typedef TPointer pointer;
486 typedef TReference reference;
487 typedef TCategory iterator_category;
488 };
489
490#if ETL_USING_CPP11
491 //***************************************************************************
492 // move_iterator
493 template <typename TIterator>
494 class move_iterator
495 {
496 public:
497
498 typedef typename iterator_traits<TIterator>::iterator_category iterator_category;
499 typedef typename iterator_traits<TIterator>::value_type value_type;
500 typedef typename iterator_traits<TIterator>::difference_type difference_type;
501 typedef TIterator iterator_type;
502 typedef TIterator pointer;
503 typedef value_type&& reference;
504
505 ETL_CONSTEXPR move_iterator()
506 : current()
507 {
508 }
509
510 ETL_CONSTEXPR explicit move_iterator(TIterator itr)
511 : current(itr)
512 {
513 }
514
515 template <typename U>
516 ETL_CONSTEXPR move_iterator(const move_iterator<U>& itr)
517 : current(itr.base())
518 {
519 }
520
521 template <typename U>
522 ETL_CONSTEXPR14 move_iterator& operator=(const move_iterator<U>& itr)
523 {
524 current = itr.current;
525 return *this;
526 }
527
528 ETL_CONSTEXPR iterator_type base() const
529 {
530 return current;
531 }
532
533 ETL_CONSTEXPR pointer operator->() const
534 {
535 return current;
536 }
537
538 ETL_CONSTEXPR reference operator*() const
539 {
540 return etl::move(*current);
541 }
542
543 ETL_CONSTEXPR14 move_iterator& operator++()
544 {
545 ++current;
546 return *this;
547 }
548
549 ETL_CONSTEXPR14 move_iterator& operator--()
550 {
551 --current;
552 return *this;
553 }
554
555 ETL_CONSTEXPR14 move_iterator operator++(int)
556 {
557 move_iterator temp = *this;
558 ++current;
559 return temp;
560 }
561
562 ETL_CONSTEXPR14 move_iterator operator--(int)
563 {
564 move_iterator temp = *this;
565 --current;
566 return temp;
567 }
568
569 ETL_CONSTEXPR move_iterator operator+(difference_type n) const
570 {
571 return move_iterator(current + n);
572 }
573
574 ETL_CONSTEXPR move_iterator operator-(difference_type n) const
575 {
576 return move_iterator(current - n);
577 }
578
579 ETL_CONSTEXPR14 move_iterator& operator+=(difference_type n)
580 {
581 current += n;
582 return *this;
583 }
584
585 ETL_CONSTEXPR14 move_iterator& operator-=(difference_type n)
586 {
587 current -= n;
588 return *this;
589 }
590
591 ETL_CONSTEXPR reference operator[](difference_type n) const
592 {
593 return etl::move(current[n]);
594 }
595
596 private:
597
598 TIterator current;
599 };
600
601 template <typename TIterator>
602 ETL_CONSTEXPR bool operator==(const etl::move_iterator<TIterator>& lhs, const etl::move_iterator<TIterator>& rhs)
603 {
604 return lhs.base() == rhs.base();
605 }
606
607 template <typename TIterator>
608 ETL_CONSTEXPR bool operator!=(const etl::move_iterator<TIterator>& lhs, const etl::move_iterator<TIterator>& rhs)
609 {
610 return !(lhs == rhs);
611 }
612
613 template <typename TIterator>
614 ETL_CONSTEXPR bool operator<(const etl::move_iterator<TIterator>& lhs, const etl::move_iterator<TIterator>& rhs)
615 {
616 return lhs.base() < rhs.base();
617 }
618
619 template <typename TIterator>
620 ETL_CONSTEXPR bool operator<=(const etl::move_iterator<TIterator>& lhs, const etl::move_iterator<TIterator>& rhs)
621 {
622 return !(rhs < lhs);
623 }
624
625 template <typename TIterator>
626 ETL_CONSTEXPR bool operator>(const etl::move_iterator<TIterator>& lhs, const etl::move_iterator<TIterator>& rhs)
627 {
628 return (rhs < lhs);
629 }
630
631 template <typename TIterator>
632 ETL_CONSTEXPR bool operator>=(const etl::move_iterator<TIterator>& lhs, const etl::move_iterator<TIterator>& rhs)
633 {
634 return !(lhs < rhs);
635 }
636
637 template <typename TIterator>
638 ETL_CONSTEXPR move_iterator<TIterator> operator+(typename move_iterator<TIterator>::difference_type n, const move_iterator<TIterator>& rhs)
639 {
640 return rhs + n;
641 }
642
643 template <typename TIterator1, typename TIterator2 >
644 ETL_CONSTEXPR auto operator-(const move_iterator<TIterator1>& lhs, const move_iterator<TIterator2>& rhs) -> decltype(lhs.base() - rhs.base())
645 {
646 return lhs.base() - rhs.base();
647 }
648
649 template <typename TIterator>
650 ETL_CONSTEXPR etl::move_iterator<TIterator> make_move_iterator(TIterator itr)
651 {
652 return etl::move_iterator<TIterator>(itr);
653 }
654
655#endif // ETL_USING_CPP11
656
657 //***************************************************************************
658 // back_insert_iterator
659 //***************************************************************************
660
661 //***************************************************************************
663 //***************************************************************************
664 template <typename TContainer>
665 class back_insert_iterator : public etl::iterator<ETL_OR_STD::output_iterator_tag, void, void, void, void>
666 {
667 public:
668
669 typedef TContainer container_type;
670
671 //***************************************************************************
673 //***************************************************************************
674 explicit ETL_CONSTEXPR14 back_insert_iterator(TContainer& c)
675 : container(etl::addressof(c))
676 {
677 }
678
679 //***************************************************************************
681 //***************************************************************************
682 ETL_CONSTEXPR14 back_insert_iterator& operator=(const typename TContainer::value_type& value)
683 {
684 container->push_back(value);
685
686 return (*this);
687 }
688
689#if ETL_USING_CPP11
690 //***************************************************************************
692 //***************************************************************************
693 ETL_CONSTEXPR14 back_insert_iterator& operator=(typename TContainer::value_type&& value)
694 {
695 container->push_back(etl::move(value));
696
697 return (*this);
698 }
699#endif // ETL_USING_CPP11
700
701 //***************************************************************************
703 //***************************************************************************
704 ETL_NODISCARD ETL_CONSTEXPR14 back_insert_iterator& operator*()
705 {
706 return (*this);
707 }
708
709 //***************************************************************************
711 //***************************************************************************
713 {
714 return (*this);
715 }
716
717 //***************************************************************************
719 //***************************************************************************
720 ETL_CONSTEXPR14 back_insert_iterator operator++(int)
721 {
722 return (*this);
723 }
724
725 protected:
726
727 TContainer* container;
728 };
729
730 //***************************************************************************
732 //***************************************************************************
733 template <typename TContainer>
734 ETL_NODISCARD ETL_CONSTEXPR14 etl::back_insert_iterator<TContainer> back_inserter(TContainer& container)
735 {
737 }
738
739 //***************************************************************************
740 // front_insert_iterator
741 //***************************************************************************
742
743 //***************************************************************************
745 //***************************************************************************
746 template <typename TContainer>
747 class front_insert_iterator : public etl::iterator<ETL_OR_STD::output_iterator_tag, void, void, void, void>
748 {
749 public:
750
751 typedef TContainer container_type;
752
753 //***************************************************************************
755 //***************************************************************************
756 explicit ETL_CONSTEXPR14 front_insert_iterator(TContainer& c)
757 : container(etl::addressof(c))
758 {
759 }
760
761 //***************************************************************************
763 //***************************************************************************
764 ETL_CONSTEXPR14 front_insert_iterator& operator=(const typename TContainer::value_type& value)
765 {
766 container->push_front(value);
767 return (*this);
768 }
769
770#if ETL_USING_CPP11
771 //***************************************************************************
773 //***************************************************************************
774 ETL_CONSTEXPR14 front_insert_iterator& operator=(typename TContainer::value_type&& value)
775 {
776 container->push_front(etl::move(value));
777 return (*this);
778 }
779#endif // ETL_USING_CPP11
780
781 //***************************************************************************
783 //***************************************************************************
784 ETL_NODISCARD ETL_CONSTEXPR14 front_insert_iterator& operator*()
785 {
786 return (*this);
787 }
788
789 //***************************************************************************
791 //***************************************************************************
793 {
794 return (*this);
795 }
796
797 //***************************************************************************
799 //***************************************************************************
801 {
802 return (*this);
803 }
804
805 protected:
806
807 TContainer* container;
808 };
809
810 //***************************************************************************
812 //***************************************************************************
813 template <typename TContainer>
814 ETL_NODISCARD ETL_CONSTEXPR14 etl::front_insert_iterator<TContainer> front_inserter(TContainer& container)
815 {
817 }
818
819 //***************************************************************************
820 // push_insert_iterator
821 //***************************************************************************
822
823 //***************************************************************************
825 //***************************************************************************
826 template <typename TContainer>
827 class push_insert_iterator : public etl::iterator<ETL_OR_STD::output_iterator_tag, void, void, void, void>
828 {
829 public:
830
831 typedef TContainer container_type;
832
833 //***************************************************************************
835 //***************************************************************************
836 explicit ETL_CONSTEXPR14 push_insert_iterator(TContainer& c)
837 : container(etl::addressof(c))
838 {
839 }
840
841 //***************************************************************************
843 //***************************************************************************
844 ETL_CONSTEXPR14 push_insert_iterator& operator=(const typename TContainer::value_type& value)
845 {
846 container->push(value);
847
848 return (*this);
849 }
850
851#if ETL_USING_CPP11
852 //***************************************************************************
854 //***************************************************************************
855 ETL_CONSTEXPR14 push_insert_iterator& operator=(typename TContainer::value_type&& value)
856 {
857 container->push(etl::move(value));
858
859 return (*this);
860 }
861#endif // ETL_USING_CPP11
862
863 //***************************************************************************
865 //***************************************************************************
866 ETL_NODISCARD ETL_CONSTEXPR14 push_insert_iterator& operator*()
867 {
868 return (*this);
869 }
870
871 //***************************************************************************
873 //***************************************************************************
875 {
876 return (*this);
877 }
878
879 //***************************************************************************
881 //***************************************************************************
882 ETL_CONSTEXPR14 push_insert_iterator operator++(int)
883 {
884 return (*this);
885 }
886
887 protected:
888
889 TContainer* container;
890 };
891
892 //***************************************************************************
894 //***************************************************************************
895 template <typename TContainer>
896 ETL_NODISCARD ETL_CONSTEXPR14 etl::push_insert_iterator<TContainer> push_inserter(TContainer& container)
897 {
899 }
900
901 //***************************************************************************
902 // Helper templates.
903 //***************************************************************************
904 template <typename T>
906 {
907 static ETL_CONSTANT bool value = etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::input_iterator_tag>::value;
908 };
909
910 template <typename T>
911 ETL_CONSTANT bool is_input_iterator<T>::value;
912
913 template <typename T>
915 {
916 static ETL_CONSTANT bool value = etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::output_iterator_tag>::value;
917 };
918
919 template <typename T>
920 ETL_CONSTANT bool is_output_iterator<T>::value;
921
922 template <typename T>
924 {
925 static ETL_CONSTANT bool value = etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::forward_iterator_tag>::value;
926 };
927
928 template <typename T>
929 ETL_CONSTANT bool is_forward_iterator<T>::value;
930
931 template <typename T>
933 {
934 static ETL_CONSTANT bool value = etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::bidirectional_iterator_tag>::value;
935 };
936
937 template <typename T>
938 ETL_CONSTANT bool is_bidirectional_iterator<T>::value;
939
940 // Deprecated
941 template <typename T>
943 {
944 static ETL_CONSTANT bool value = etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::random_access_iterator_tag>::value;
945 };
946
947 template <typename T>
948 ETL_CONSTANT bool is_random_iterator<T>::value;
949
950 template <typename T>
952 {
953 static ETL_CONSTANT bool value = etl::is_same<typename etl::iterator_traits<T>::iterator_category, ETL_OR_STD::random_access_iterator_tag>::value;
954 };
955
956 template <typename T>
957 ETL_CONSTANT bool is_random_access_iterator<T>::value;
958
959 template <typename T>
961 {
962 static
963 ETL_CONSTANT bool value = etl::is_input_iterator<T>::value || etl::is_forward_iterator<T>::value || etl::is_bidirectional_iterator<T>::value
964 || etl::is_random_iterator<T>::value;
965 };
966
967 template <typename T>
968 ETL_CONSTANT bool is_input_iterator_concept<T>::value;
969
970 template <typename T>
972 {
973 static
974 ETL_CONSTANT bool value = etl::is_output_iterator<T>::value || etl::is_forward_iterator<T>::value || etl::is_bidirectional_iterator<T>::value
975 || etl::is_random_iterator<T>::value;
976 };
977
978 template <typename T>
979 ETL_CONSTANT bool is_output_iterator_concept<T>::value;
980
981 template <typename T>
983 {
984 static
985 ETL_CONSTANT bool value = etl::is_forward_iterator<T>::value || etl::is_bidirectional_iterator<T>::value || etl::is_random_iterator<T>::value;
986 };
987
988 template <typename T>
989 ETL_CONSTANT bool is_forward_iterator_concept<T>::value;
990
991 template <typename T>
993 {
994 static ETL_CONSTANT bool value = etl::is_bidirectional_iterator<T>::value || etl::is_random_iterator<T>::value;
995 };
996
997 template <typename T>
998 ETL_CONSTANT bool is_bidirectional_iterator_concept<T>::value;
999
1000 // Deprecated
1001 template <typename T>
1003 {
1004 static ETL_CONSTANT bool value = etl::is_random_iterator<T>::value;
1005 };
1006
1007 // Deprecated
1008 template <typename T>
1009 ETL_CONSTANT bool is_random_iterator_concept<T>::value;
1010
1011 // Deprecated
1012 template <typename T>
1014 {
1015 static ETL_CONSTANT bool value = etl::is_random_access_iterator<T>::value;
1016 };
1017
1018 // Deprecated
1019 template <typename T>
1020 ETL_CONSTANT bool is_random_access_iterator_concept<T>::value;
1021
1022#if ETL_USING_CPP11
1023 //***************************************************************************
1027 //***************************************************************************
1028 namespace private_iterator
1029 {
1030 // Check if T has iterator_category (i.e., is an iterator)
1031 template <typename T, typename = void>
1032 struct has_iterator_category : etl::false_type
1033 {
1034 };
1035
1036 template <typename T>
1037 struct has_iterator_category<T, etl::void_t<typename T::iterator_category>> : etl::true_type
1038 {
1039 };
1040
1041 // is_container: has iterator/const_iterator/begin/end but does NOT have iterator_category
1042 template <typename T, typename = void>
1043 struct is_container : etl::false_type
1044 {
1045 };
1046
1047 template <typename T>
1048 struct is_container<
1049 T, etl::void_t< typename T::iterator, typename T::const_iterator, decltype(etl::declval<T&>().begin()), decltype(etl::declval<T&>().end()) >>
1050 : etl::bool_constant<!has_iterator_category<T>::value>
1051 {
1052 };
1053 } // namespace private_iterator
1054#endif
1055
1056#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED
1057 #if ETL_USING_CPP11
1058
1059 //*****************************************************************************
1066 //*****************************************************************************
1067 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().begin())> >
1068 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::iterator>::type
1069 begin(TContainer& container)
1070 {
1071 return container.begin();
1072 }
1073
1074 //*****************************************************************************
1077 //*****************************************************************************
1078 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().begin())> >
1079 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_iterator>::type
1080 begin(const TContainer& container)
1081 {
1082 return container.begin();
1083 }
1084
1085 //*****************************************************************************
1088 //*****************************************************************************
1089 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().cbegin())> >
1090 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_iterator>::type
1091 cbegin(const TContainer& container)
1092 {
1093 return container.cbegin();
1094 }
1095
1096 //*****************************************************************************
1099 //*****************************************************************************
1100 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().end())> >
1101 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::iterator>::type end(TContainer& container)
1102 {
1103 return container.end();
1104 }
1105
1106 //*****************************************************************************
1109 //*****************************************************************************
1110 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().end())> >
1111 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_iterator>::type
1112 end(const TContainer& container)
1113 {
1114 return container.end();
1115 }
1116
1117 //*****************************************************************************
1120 //*****************************************************************************
1121 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().cend())> >
1122 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_iterator>::type
1123 cend(const TContainer& container)
1124 {
1125 return container.cend();
1126 }
1127 #else
1128 // C++03 fallback:
1129 // - no SFINAE guards needed since std::ranges does not exist
1130 // - no constraint needed as C++26 ADL issue doesn't apply
1131 //*****************************************************************************
1134 //*****************************************************************************
1135 template <typename TContainer>
1136 typename TContainer::iterator begin(TContainer& container)
1137 {
1138 return container.begin();
1139 }
1140
1141 //*****************************************************************************
1144 //*****************************************************************************
1145 template <typename TContainer>
1146 typename TContainer::const_iterator begin(const TContainer& container)
1147 {
1148 return container.begin();
1149 }
1150
1151 //*****************************************************************************
1154 //*****************************************************************************
1155 template <typename TContainer>
1156 typename TContainer::const_iterator cbegin(const TContainer& container)
1157 {
1158 return container.cbegin();
1159 }
1160
1161 //*****************************************************************************
1164 //*****************************************************************************
1165 template <typename TContainer>
1166 typename TContainer::iterator end(TContainer& container)
1167 {
1168 return container.end();
1169 }
1170
1171 //*****************************************************************************
1174 //*****************************************************************************
1175 template <typename TContainer>
1176 typename TContainer::const_iterator end(const TContainer& container)
1177 {
1178 return container.end();
1179 }
1180
1181 //*****************************************************************************
1184 //*****************************************************************************
1185 template <typename TContainer>
1186 typename TContainer::const_iterator cend(const TContainer& container)
1187 {
1188 return container.cend();
1189 }
1190 #endif
1191
1192 //*****************************************************************************
1195 //*****************************************************************************
1196 template <typename TValue, size_t Array_Size>
1197 ETL_CONSTEXPR TValue* begin(TValue (&data)[Array_Size])
1198 {
1199 return &data[0];
1200 }
1201
1202 //*****************************************************************************
1205 //*****************************************************************************
1206 template <typename TValue, size_t Array_Size>
1207 ETL_CONSTEXPR const TValue* begin(const TValue (&data)[Array_Size])
1208 {
1209 return &data[0];
1210 }
1211
1212 //*****************************************************************************
1215 //*****************************************************************************
1216 template <typename TValue, size_t Array_Size>
1217 ETL_CONSTEXPR const TValue* cbegin(const TValue (&data)[Array_Size])
1218 {
1219 return &data[0];
1220 }
1221
1222 //*****************************************************************************
1225 //*****************************************************************************
1226 template <typename TValue, size_t Array_Size>
1227 ETL_CONSTEXPR TValue* end(TValue (&data)[Array_Size])
1228 {
1229 return &data[Array_Size];
1230 }
1231
1232 //*****************************************************************************
1235 //*****************************************************************************
1236 template <typename TValue, size_t Array_Size>
1237 ETL_CONSTEXPR const TValue* end(const TValue (&data)[Array_Size])
1238 {
1239 return &data[Array_Size];
1240 }
1241
1242 //*****************************************************************************
1245 //*****************************************************************************
1246 template <typename TValue, size_t Array_Size>
1247 ETL_CONSTEXPR const TValue* cend(const TValue (&data)[Array_Size])
1248 {
1249 return &data[Array_Size];
1250 }
1251#endif
1252
1253#if ETL_NOT_USING_STL || ETL_CPP14_NOT_SUPPORTED
1254 #if ETL_USING_CPP11
1255 //*****************************************************************************
1259 //*****************************************************************************
1260 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().rbegin())> >
1261 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::reverse_iterator>::type
1262 rbegin(TContainer& container)
1263 {
1264 return container.rbegin();
1265 }
1266
1267 //*****************************************************************************
1270 //*****************************************************************************
1271 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().rbegin())> >
1272 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_reverse_iterator>::type
1273 rbegin(const TContainer& container)
1274 {
1275 return container.rbegin();
1276 }
1277
1278 //*****************************************************************************
1281 //*****************************************************************************
1282 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().crbegin())> >
1283 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_reverse_iterator>::type
1284 crbegin(const TContainer& container)
1285 {
1286 return container.crbegin();
1287 }
1288
1289 //*****************************************************************************
1292 //*****************************************************************************
1293 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<TContainer&>().rend())> >
1294 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::reverse_iterator>::type
1295 rend(TContainer& container)
1296 {
1297 return container.rend();
1298 }
1299
1300 //*****************************************************************************
1303 //*****************************************************************************
1304 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().rend())> >
1305 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_reverse_iterator>::type
1306 rend(const TContainer& container)
1307 {
1308 return container.rend();
1309 }
1310
1311 //*****************************************************************************
1314 //*****************************************************************************
1315 template <typename TContainer, typename = etl::void_t<decltype(etl::declval<const TContainer&>().crend())> >
1316 ETL_CONSTEXPR typename etl::enable_if<private_iterator::is_container<TContainer>::value, typename TContainer::const_reverse_iterator>::type
1317 crend(const TContainer& container)
1318 {
1319 return container.crend();
1320 }
1321 #else
1322 // C++03 fallback:
1323 // - no SFINAE guards needed since std::ranges does not exist.
1324 // - no constraint needed as C++26 ADL issue doesn't apply
1325 //*****************************************************************************
1328 //*****************************************************************************
1329 template <typename TContainer>
1330 typename TContainer::reverse_iterator rbegin(TContainer& container)
1331 {
1332 return container.rbegin();
1333 }
1334
1335 //*****************************************************************************
1338 //*****************************************************************************
1339 template <typename TContainer>
1340 typename TContainer::const_reverse_iterator rbegin(const TContainer& container)
1341 {
1342 return container.rbegin();
1343 }
1344
1345 //*****************************************************************************
1348 //*****************************************************************************
1349 template <typename TContainer>
1350 typename TContainer::const_reverse_iterator crbegin(const TContainer& container)
1351 {
1352 return container.crbegin();
1353 }
1354
1355 //*****************************************************************************
1358 //*****************************************************************************
1359 template <typename TContainer>
1360 typename TContainer::reverse_iterator rend(TContainer& container)
1361 {
1362 return container.rend();
1363 }
1364
1365 //*****************************************************************************
1368 //*****************************************************************************
1369 template <typename TContainer>
1370 typename TContainer::const_reverse_iterator rend(const TContainer& container)
1371 {
1372 return container.rend();
1373 }
1374
1375 //*****************************************************************************
1378 //*****************************************************************************
1379 template <typename TContainer>
1380 typename TContainer::const_reverse_iterator crend(const TContainer& container)
1381 {
1382 return container.crend();
1383 }
1384 #endif
1385
1386 //*****************************************************************************
1389 //*****************************************************************************
1390 template <typename TValue, size_t Array_Size>
1391 ETL_OR_STD::reverse_iterator<TValue*> rbegin(TValue (&data)[Array_Size])
1392 {
1393 return ETL_OR_STD::reverse_iterator<TValue*>(&data[Array_Size]);
1394 }
1395
1396 //*****************************************************************************
1399 //*****************************************************************************
1400 template <typename TValue, size_t Array_Size>
1401 ETL_CONSTEXPR ETL_OR_STD::reverse_iterator<const TValue*> crbegin(const TValue (&data)[Array_Size])
1402 {
1403 return ETL_OR_STD::reverse_iterator<const TValue*>(&data[Array_Size]);
1404 }
1405
1406 //*****************************************************************************
1409 //*****************************************************************************
1410 template <typename TValue, size_t Array_Size>
1411 ETL_CONSTEXPR ETL_OR_STD::reverse_iterator<TValue*> rend(TValue (&data)[Array_Size])
1412 {
1413 return ETL_OR_STD::reverse_iterator<TValue*>(&data[0]);
1414 }
1415
1416 //*****************************************************************************
1419 //*****************************************************************************
1420 template <typename TValue, size_t Array_Size>
1421 ETL_CONSTEXPR ETL_OR_STD::reverse_iterator<const TValue*> crend(const TValue (&data)[Array_Size])
1422 {
1423 return ETL_OR_STD::reverse_iterator<const TValue*>(&data[0]);
1424 }
1425#endif
1426
1427#if ETL_NOT_USING_STL || ETL_CPP17_NOT_SUPPORTED
1428 //**************************************************************************
1432 //**************************************************************************
1433 template <typename TContainer>
1434 ETL_CONSTEXPR typename TContainer::size_type size(const TContainer& container)
1435 {
1436 return container.size();
1437 }
1438
1444 template <typename TValue, size_t Array_Size>
1445 ETL_CONSTEXPR size_t size(TValue (&)[Array_Size])
1446 {
1447 return Array_Size;
1448 }
1449#endif
1450
1451 //**************************************************************************
1457 //**************************************************************************
1458 template <typename T, size_t Array_Size>
1459 char (&array_size(T (&array)[Array_Size]))[Array_Size];
1460
1461#define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a))
1462
1463#if ETL_NOT_USING_STL || ETL_CPP17_NOT_SUPPORTED
1464 //**************************************************************************
1468 //**************************************************************************
1469 template <typename TContainer>
1470 ETL_CONSTEXPR typename TContainer::pointer data(TContainer& container)
1471 {
1472 return container.data();
1473 }
1474
1475 //**************************************************************************
1479 //**************************************************************************
1480 template <typename TContainer>
1481 ETL_CONSTEXPR typename TContainer::const_pointer data(const TContainer& container)
1482 {
1483 return container.data();
1484 }
1485
1491 template <typename TValue, size_t Array_Size>
1492 ETL_CONSTEXPR TValue* data(TValue (&a)[Array_Size])
1493 {
1494 return a;
1495 }
1496
1502 template <typename TValue, size_t Array_Size>
1503 ETL_CONSTEXPR const TValue* data(const TValue (&a)[Array_Size])
1504 {
1505 return a;
1506 }
1507#endif
1508
1509#if ETL_USING_CPP17
1510 template <class T>
1511 using iter_value_t = typename etl::iterator_traits<etl::remove_cvref_t<T>>::value_type;
1512
1513 template <class T>
1514 using iter_reference_t = decltype(*etl::declval<T&>());
1515
1516 #if ETL_USING_CPP20
1517 template <class T>
1518 using iter_const_reference_t = typename etl::common_reference_t<const etl::iter_value_t<T>&&, etl::iter_reference_t<T>>;
1519 #endif
1520
1521 template <class T>
1522 using iter_difference_t = typename etl::iterator_traits<etl::remove_cvref_t<T>>::difference_type;
1523
1524 template <class I, class Proj>
1525 using projected_value_t = etl::remove_cvref_t<etl::invoke_result_t<Proj&, etl::iter_reference_t<I>>>;
1526
1527 namespace ranges
1528 {
1529 namespace private_ranges
1530 {
1531 struct begin
1532 {
1533 template <class T>
1534 constexpr auto operator()(T& t) const
1535 {
1536 return ETL_OR_STD::begin(t);
1537 }
1538 };
1539
1540 struct end
1541 {
1542 template <class T>
1543 constexpr auto operator()(T& t) const
1544 {
1545 return ETL_OR_STD::end(t);
1546 }
1547 };
1548
1549 struct cbegin
1550 {
1551 template <class T>
1552 constexpr auto operator()(T& t) const
1553 {
1554 return ETL_OR_STD::cbegin(t);
1555 }
1556 };
1557
1558 struct cend
1559 {
1560 template <class T>
1561 constexpr auto operator()(T& t) const
1562 {
1563 return ETL_OR_STD::cend(t);
1564 }
1565 };
1566
1567 struct rbegin
1568 {
1569 template <class T>
1570 constexpr auto operator()(T& t) const
1571 {
1572 return ETL_OR_STD::rbegin(t);
1573 }
1574 };
1575
1576 struct rend
1577 {
1578 template <class T>
1579 constexpr auto operator()(T& t) const
1580 {
1581 return ETL_OR_STD::rend(t);
1582 }
1583 };
1584
1585 struct crbegin
1586 {
1587 template <class T>
1588 constexpr auto operator()(T& t) const
1589 {
1590 return ETL_OR_STD::crbegin(t);
1591 }
1592 };
1593
1594 struct crend
1595 {
1596 template <class T>
1597 constexpr auto operator()(T& t) const
1598 {
1599 return ETL_OR_STD::crend(t);
1600 }
1601 };
1602
1603 template <class T, class = void>
1604 struct has_size_member : etl::false_type
1605 {
1606 };
1607
1608 template <class T>
1609 struct has_size_member< T, etl::void_t<decltype(etl::declval<const T&>().size())>> : etl::true_type
1610 {
1611 };
1612
1613 template <class T, class = void>
1614 struct has_empty_member : etl::false_type
1615 {
1616 };
1617
1618 template <class T>
1619 struct has_empty_member< T, etl::void_t<decltype(etl::declval<const T&>().empty())>> : etl::true_type
1620 {
1621 };
1622
1623 struct distance
1624 {
1625 // Overload for common ranges (iterator == sentinel type)
1626 template <typename I, typename = etl::enable_if_t< etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value>>
1627 constexpr etl::iter_difference_t<I> operator()(I first, I last) const
1628 {
1629 if constexpr (etl::is_random_access_iterator_concept<I>::value)
1630 {
1631 return last - first;
1632 }
1633 else
1634 {
1635 etl::iter_difference_t<I> n = 0;
1636 while (!(first == last))
1637 {
1638 ++first;
1639 ++n;
1640 }
1641 return n;
1642 }
1643 }
1644
1645 // Overload for non-common ranges (iterator != sentinel type)
1646 template <typename I, typename S,
1647 typename = etl::enable_if_t< (etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value)
1648 && !etl::is_same<I, S>::value>>
1649 constexpr etl::iter_difference_t<I> operator()(I first, S last) const
1650 {
1651 etl::iter_difference_t<I> n = 0;
1652 while (!(first == last))
1653 {
1654 ++first;
1655 ++n;
1656 }
1657 return n;
1658 }
1659 };
1660
1661 struct size
1662 {
1663 template <class T>
1664 constexpr size_t operator()(T&& t) const
1665 {
1666 using U = etl::remove_cvref_t<T>;
1667
1668 if constexpr (has_size_member<U>::value)
1669 {
1670 return static_cast<size_t>(t.size());
1671 }
1672 else
1673 {
1674 using iter_type = decltype(ETL_OR_STD::begin(t));
1675 static_assert(etl::is_forward_iterator_concept<iter_type>::value, "ranges::size requires a sized range or at least a forward range; "
1676 "single-pass input ranges are not supported");
1677 return static_cast<size_t>(distance{}(ETL_OR_STD::begin(t), ETL_OR_STD::end(t)));
1678 }
1679 }
1680 };
1681
1682 struct ssize
1683 {
1684 template <class T>
1685 constexpr auto operator()(T&& t) const
1686 {
1687 using U = etl::remove_cvref_t<T>;
1688
1689 if constexpr (has_size_member<U>::value)
1690 {
1691 return static_cast<ptrdiff_t>(t.size());
1692 }
1693 else
1694 {
1695 using iter_type = decltype(ETL_OR_STD::begin(t));
1696 static_assert(etl::is_forward_iterator_concept<iter_type>::value, "ranges::ssize requires a sized range or at least a forward range; "
1697 "single-pass input ranges are not supported");
1698 return static_cast<ptrdiff_t>(distance{}(ETL_OR_STD::begin(t), ETL_OR_STD::end(t)));
1699 }
1700 }
1701 };
1702
1703 struct empty
1704 {
1705 template <class T>
1706 constexpr auto operator()(T&& t) const
1707 {
1708 using U = etl::remove_cvref_t<T>;
1709
1710 if constexpr (has_empty_member<U>::value)
1711 {
1712 return t.empty();
1713 }
1714 else
1715 {
1716 return ETL_OR_STD::cbegin(t) == ETL_OR_STD::cend(t);
1717 }
1718 }
1719 };
1720
1721 struct data
1722 {
1723 template <class T>
1724 constexpr auto operator()(T& t) const
1725 {
1726 return ETL_OR_STD::data(t);
1727 }
1728 };
1729
1730 struct cdata
1731 {
1732 template <class T>
1733 constexpr etl::add_pointer_t< etl::add_const_t<etl::remove_pointer_t< decltype(ETL_OR_STD::data(etl::declval<T&>()))>>> operator()(T& t) const
1734 {
1735 return ETL_OR_STD::data(t);
1736 }
1737 };
1738 } // namespace private_ranges
1739
1740 inline constexpr private_ranges::begin begin;
1741 inline constexpr private_ranges::end end;
1742 inline constexpr private_ranges::cbegin cbegin;
1743 inline constexpr private_ranges::cend cend;
1744 inline constexpr private_ranges::rbegin rbegin;
1745 inline constexpr private_ranges::rend rend;
1746 inline constexpr private_ranges::crbegin crbegin;
1747 inline constexpr private_ranges::crend crend;
1748 inline constexpr private_ranges::size size;
1749 inline constexpr private_ranges::ssize ssize;
1750 inline constexpr private_ranges::empty empty;
1751 inline constexpr private_ranges::data data;
1752 inline constexpr private_ranges::cdata cdata;
1753 inline constexpr private_ranges::distance distance;
1754
1755 //*************************************************************************
1757 //*************************************************************************
1758
1759 template <class T>
1760 using iterator_t = decltype(etl::ranges::begin(etl::declval<T&>()));
1761
1762 template <class T>
1763 using const_iterator_t = decltype(etl::ranges::cbegin(etl::declval<T&>()));
1764
1765 template <class T>
1766 using sentinel_t = decltype(etl::ranges::end(etl::declval<T&>()));
1767
1768 template <class T>
1769 using const_sentinel_t = decltype(etl::ranges::cend(etl::declval<T&>()));
1770
1771 template <class T>
1772 using range_size_t = decltype(etl::ranges::size(etl::declval<T&>()));
1773
1774 template <class T>
1775 using range_difference_t = etl::iter_difference_t<etl::ranges::iterator_t<T>>;
1776
1777 template <class T>
1778 using range_value_t = etl::iter_value_t<etl::ranges::iterator_t<T>>;
1779
1780 template <class T>
1781 using range_reference_t = etl::iter_reference_t<ranges::iterator_t<T>>;
1782
1783 struct advance_fn
1784 {
1785 template <typename I, typename = etl::enable_if_t< (etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value)
1786 && etl::is_integral<etl::iter_difference_t<I>>::value>>
1787 constexpr void operator()(I& i, etl::iter_difference_t<I> n) const
1788 {
1789 if constexpr (etl::is_random_access_iterator_concept<I>::value)
1790 {
1791 i += n;
1792 }
1793 else
1794 {
1795 while (n > 0)
1796 {
1797 --n;
1798 ++i;
1799 }
1800
1801 if constexpr (etl::is_bidirectional_iterator_concept<I>::value)
1802 {
1803 while (n < 0)
1804 {
1805 ++n;
1806 --i;
1807 }
1808 }
1809 }
1810 }
1811
1812 template <typename I, typename S,
1813 typename = etl::enable_if_t< (etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value)
1814 && !etl::is_integral<S>::value>>
1815 constexpr void operator()(I& i, S bound) const
1816 {
1817 if constexpr (etl::is_assignable_v<I&, S>)
1818 {
1819 i = etl::move(bound);
1820 }
1821 else if constexpr (etl::is_same_v<S, I> && etl::is_random_access_iterator_concept<I>::value)
1822 {
1823 (*this)(i, bound - i);
1824 }
1825 else
1826 {
1827 while (!(i == bound))
1828 {
1829 ++i;
1830 }
1831 }
1832 }
1833
1834 template <typename I, typename S,
1835 typename = etl::enable_if_t< etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value>>
1836 constexpr etl::iter_difference_t<I> operator()(I& i, etl::iter_difference_t<I> n, S bound) const
1837 {
1838 if constexpr (etl::is_same_v<S, I> && etl::is_random_access_iterator_concept<I>::value)
1839 {
1840 const auto dist = bound - i;
1841
1842 if ((n >= 0 && dist >= 0 && n >= dist) || (n <= 0 && dist <= 0 && n <= dist))
1843 {
1844 (*this)(i, bound);
1845 return n - dist;
1846 }
1847
1848 (*this)(i, n);
1849 return 0;
1850 }
1851 else
1852 {
1853 while (n > 0 && !(i == bound))
1854 {
1855 --n;
1856 ++i;
1857 }
1858
1859 if constexpr (etl::is_bidirectional_iterator_concept<I>::value)
1860 {
1861 while (n < 0 && !(i == bound))
1862 {
1863 ++n;
1864 --i;
1865 }
1866 }
1867
1868 return n;
1869 }
1870 }
1871 };
1872
1873 inline constexpr auto advance = advance_fn();
1874
1875 struct prev_fn
1876 {
1877 template <typename I, typename = etl::enable_if_t< etl::is_bidirectional_iterator_concept<I>::value>>
1878 constexpr I operator()(I i) const
1879 {
1880 --i;
1881 return i;
1882 }
1883
1884 template <typename I, typename = etl::enable_if_t< etl::is_bidirectional_iterator_concept<I>::value>>
1885 constexpr I operator()(I i, etl::iter_difference_t<I> n) const
1886 {
1887 ranges::advance(i, -n);
1888 return i;
1889 }
1890
1891 template <typename I, typename = etl::enable_if_t< etl::is_bidirectional_iterator_concept<I>::value>>
1892 constexpr I operator()(I i, etl::iter_difference_t<I> n, I bound) const
1893 {
1894 ranges::advance(i, -n, bound);
1895 return i;
1896 }
1897 };
1898
1899 inline constexpr auto prev = prev_fn();
1900
1901 struct next_fn
1902 {
1903 template <typename I, typename = etl::enable_if_t< etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value>>
1904 constexpr I operator()(I i) const
1905 {
1906 ++i;
1907 return i;
1908 }
1909
1910 template <typename I, typename = etl::enable_if_t< (etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value)
1911 && etl::is_integral<etl::iter_difference_t<I>>::value>>
1912 constexpr I operator()(I i, etl::iter_difference_t<I> n) const
1913 {
1914 ranges::advance(i, n);
1915 return i;
1916 }
1917
1918 template <typename I, typename S,
1919 typename = etl::enable_if_t< (etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value)
1920 && !etl::is_integral<S>::value>>
1921 constexpr I operator()(I i, S bound) const
1922 {
1923 ranges::advance(i, bound);
1924 return i;
1925 }
1926
1927 template <typename I, typename S,
1928 typename = etl::enable_if_t< (etl::is_input_iterator_concept<I>::value || etl::is_output_iterator_concept<I>::value)
1929 && !etl::is_integral<S>::value>>
1930 constexpr I operator()(I i, etl::iter_difference_t<I> n, S bound) const
1931 {
1932 ranges::advance(i, n, bound);
1933 return i;
1934 }
1935 };
1936
1937 inline constexpr auto next = next_fn();
1938 } // namespace ranges
1939
1940 struct unreachable_sentinel_t
1941 {
1942 };
1943
1944 inline constexpr unreachable_sentinel_t unreachable_sentinel{};
1945
1946 template <typename I>
1947 constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept
1948 {
1949 return false;
1950 }
1951
1952 template <typename I>
1953 constexpr bool operator==(const I&, unreachable_sentinel_t) noexcept
1954 {
1955 return false;
1956 }
1957
1958 template <typename I>
1959 constexpr bool operator!=(unreachable_sentinel_t, const I& i) noexcept
1960 {
1961 return !(unreachable_sentinel_t{} == i);
1962 }
1963
1964 template <typename I>
1965 constexpr bool operator!=(const I& i, unreachable_sentinel_t) noexcept
1966 {
1967 return !(i == unreachable_sentinel_t{});
1968 }
1969
1970 struct default_sentinel_t
1971 {
1972 };
1973
1974 inline constexpr default_sentinel_t default_sentinel{};
1975
1976 namespace private_iterator
1977 {
1978 template <typename T, typename = void>
1979 struct has_arrow_operator : etl::false_type
1980 {
1981 };
1982
1983 template <typename T>
1984 struct has_arrow_operator< T, etl::void_t<decltype(etl::declval<const T&>().operator->())>> : etl::true_type
1985 {
1986 };
1987
1988 //***********************************
1993 //***********************************
1994 template <typename TValue>
1995 struct arrow_proxy
1996 {
1997 TValue stored;
1998
1999 constexpr arrow_proxy(TValue value)
2000 : stored(etl::move(value))
2001 {
2002 }
2003 constexpr const TValue* operator->() const noexcept
2004 {
2005 return etl::addressof(stored);
2006 }
2007 };
2008 } // namespace private_iterator
2009
2010 template <class I>
2011 class counted_iterator
2012 {
2013 template <class>
2014 friend class counted_iterator;
2015
2016 public:
2017
2018 using iterator_type = I;
2019 using value_type = etl::iter_value_t<I>;
2020 using difference_type = etl::iter_difference_t<I>;
2021 using iterator_category = typename etl::iterator_traits<iterator_type>::iterator_category;
2022 using pointer = typename etl::iterator_traits<iterator_type>::pointer;
2023 using reference = typename etl::iterator_traits<iterator_type>::reference;
2024
2025 constexpr counted_iterator() = default;
2026
2027 constexpr counted_iterator(I x, etl::iter_difference_t<I> n)
2028 : current(etl::move(x))
2029 , length(n)
2030 {
2031 }
2032
2033 template <class I2>
2034 constexpr counted_iterator(const counted_iterator<I2>& other)
2035 : current(other.current)
2036 , length(other.length)
2037 {
2038 }
2039
2040 template <class I2>
2041 constexpr counted_iterator& operator=(const counted_iterator<I2>& other)
2042 {
2043 current = other.current;
2044 length = other.length;
2045 return *this;
2046 }
2047
2048 constexpr const I& base() const& noexcept
2049 {
2050 return current;
2051 }
2052
2053 constexpr I base() &&
2054 {
2055 return etl::move(current);
2056 }
2057
2058 constexpr etl::iter_difference_t<I> count() const noexcept
2059 {
2060 return length;
2061 }
2062
2063 constexpr decltype(auto) operator*() const
2064 {
2065 return *current;
2066 }
2067
2068 // operator-> for iterator types that provide a member operator->
2069 template < typename J = I, etl::enable_if_t<(etl::is_input_iterator_concept<J>::value || etl::is_output_iterator_concept<J>::value)
2070 && private_iterator::has_arrow_operator<J>::value,
2071 int> = 0>
2072 constexpr auto operator->() const noexcept
2073 {
2074 return current.operator->();
2075 }
2076
2077 // operator-> fallback for raw-pointer iterators (addressof is always safe)
2078 template < typename J = I, etl::enable_if_t<(etl::is_input_iterator_concept<J>::value || etl::is_output_iterator_concept<J>::value)
2079 && !private_iterator::has_arrow_operator<J>::value && etl::is_pointer<J>::value,
2080 int> = 0>
2081 constexpr auto operator->() const noexcept
2082 {
2083 return current;
2084 }
2085
2086 // operator-> fallback for class-type iterators without member operator->
2087 // When *current yields an lvalue reference, just take its address.
2088 template < typename J = I, etl::enable_if_t< (etl::is_input_iterator_concept<J>::value || etl::is_output_iterator_concept<J>::value)
2089 && !private_iterator::has_arrow_operator<J>::value && !etl::is_pointer<J>::value
2090 && etl::is_lvalue_reference< decltype(*etl::declval<const J&>())>::value,
2091 int> = 0>
2092 constexpr auto operator->() const noexcept
2093 {
2094 return etl::addressof(*current);
2095 }
2096
2097 // operator-> fallback for class-type iterators without member operator->
2098 // When *current yields a prvalue / proxy, use an owning proxy so the
2099 // address remains valid.
2100 template < typename J = I, etl::enable_if_t< (etl::is_input_iterator_concept<J>::value || etl::is_output_iterator_concept<J>::value)
2101 && !private_iterator::has_arrow_operator<J>::value && !etl::is_pointer<J>::value
2102 && !etl::is_lvalue_reference< decltype(*etl::declval<const J&>())>::value,
2103 int> = 0>
2104 constexpr auto operator->() const
2105 {
2106 return private_iterator::arrow_proxy<value_type>{*current};
2107 }
2108
2109 template < typename J = I, etl::enable_if_t<etl::is_random_access_iterator<J>::value, int> = 0>
2110 constexpr decltype(auto) operator[](etl::iter_difference_t<I> n) const
2111 {
2112 return current[n];
2113 }
2114
2115 constexpr counted_iterator& operator++()
2116 {
2117 ++current;
2118 --length;
2119 return *this;
2120 }
2121
2122 constexpr counted_iterator operator++(int)
2123 {
2124 counted_iterator tmp = *this;
2125 current++;
2126 length--;
2127 return tmp;
2128 }
2129
2130 template < typename J = I, etl::enable_if_t<etl::is_random_access_iterator<J>::value, int> = 0>
2131 constexpr counted_iterator& operator+=(etl::iter_difference_t<I> n)
2132 {
2133 current += n;
2134 length -= n;
2135 return *this;
2136 }
2137
2138 template < typename J = I, etl::enable_if_t<etl::is_random_access_iterator<J>::value, int> = 0>
2139 constexpr counted_iterator operator+(etl::iter_difference_t<I> n) const
2140 {
2141 counted_iterator result{*this};
2142 result += n;
2143 return result;
2144 }
2145
2146 constexpr counted_iterator& operator--()
2147 {
2148 --current;
2149 ++length;
2150 return *this;
2151 }
2152
2153 constexpr counted_iterator operator--(int)
2154 {
2155 counted_iterator tmp = *this;
2156 current--;
2157 length++;
2158 return tmp;
2159 }
2160
2161 template < typename J = I, etl::enable_if_t<etl::is_random_access_iterator<J>::value, int> = 0>
2162 constexpr counted_iterator& operator-=(etl::iter_difference_t<I> n)
2163 {
2164 current -= n;
2165 length += n;
2166 return *this;
2167 }
2168
2169 template < typename J = I, etl::enable_if_t<etl::is_random_access_iterator<J>::value, int> = 0>
2170 constexpr counted_iterator operator-(etl::iter_difference_t<I> n) const
2171 {
2172 counted_iterator result{*this};
2173 result -= n;
2174 return result;
2175 }
2176
2177 friend constexpr bool operator==(const counted_iterator& x, const counted_iterator& y)
2178 {
2179 return x.length == y.length;
2180 }
2181
2182 friend constexpr bool operator==(const counted_iterator& x, etl::default_sentinel_t)
2183 {
2184 return x.count() == 0;
2185 }
2186
2187 friend constexpr bool operator==(etl::default_sentinel_t, const counted_iterator& x)
2188 {
2189 return x.count() == 0;
2190 }
2191
2192 friend constexpr bool operator!=(const counted_iterator& x, etl::default_sentinel_t)
2193 {
2194 return x.count() != 0;
2195 }
2196
2197 friend constexpr bool operator!=(etl::default_sentinel_t, const counted_iterator& y)
2198 {
2199 return y.count() != 0;
2200 }
2201
2202 template < typename J = I, etl::enable_if_t<etl::is_random_access_iterator<J>::value, int> = 0>
2203 friend constexpr counted_iterator operator+(etl::iter_difference_t<I> n, const counted_iterator& x)
2204 {
2205 return counted_iterator(x.current + n, x.length - n);
2206 }
2207
2208 friend constexpr etl::iter_difference_t<I> operator-(const counted_iterator& x, const counted_iterator& y)
2209 {
2210 return y.length - x.length;
2211 }
2212
2213 friend constexpr etl::iter_difference_t<I> operator-(const counted_iterator& x, etl::default_sentinel_t)
2214 {
2215 return -x.length;
2216 }
2217
2218 friend constexpr etl::iter_difference_t<I> operator-(etl::default_sentinel_t, const counted_iterator& y)
2219 {
2220 return y.length;
2221 }
2222
2223 private:
2224
2225 I current{};
2226 difference_type length{};
2227 };
2228
2229 template <typename TIterator,
2230 typename = etl::enable_if_t<etl::is_base_of< etl::counted_iterator<typename TIterator::iterator_type>, TIterator>::value>>
2231 constexpr typename etl::iterator_traits<TIterator>::difference_type distance(TIterator first, etl::default_sentinel_t)
2232 {
2233 return first.count();
2234 }
2235#endif
2236
2237#if ETL_USING_CPP14
2238 template <class T, typename = void>
2239 struct is_range : etl::false_type
2240 {
2241 };
2242
2243 template <class T>
2244 struct is_range< T, etl::void_t<decltype(ETL_OR_STD::begin(etl::declval<T&>())), decltype(ETL_OR_STD::end(etl::declval<T&>()))>> : etl::true_type
2245 {
2246 };
2247
2248 #if ETL_USING_CPP17
2249 template <typename T>
2250 inline constexpr bool is_range_v = is_range<T>::value;
2251 #endif
2252#endif
2253} // namespace etl
2254
2255#endif
Turns assignment into push_back.
Definition iterator.h:666
ETL_CONSTEXPR14 back_insert_iterator & operator++()
Pre-increment operator.
Definition iterator.h:712
ETL_CONSTEXPR14 back_insert_iterator(TContainer &c)
Constructor.
Definition iterator.h:674
ETL_CONSTEXPR14 back_insert_iterator & operator=(const typename TContainer::value_type &value)
Assignment operator.
Definition iterator.h:682
ETL_NODISCARD ETL_CONSTEXPR14 back_insert_iterator & operator*()
Dereference operator.
Definition iterator.h:704
ETL_CONSTEXPR14 back_insert_iterator operator++(int)
Post-increment operator.
Definition iterator.h:720
Turns assignment into a push_front.
Definition iterator.h:748
ETL_CONSTEXPR14 front_insert_iterator(TContainer &c)
Constructor.
Definition iterator.h:756
ETL_CONSTEXPR14 front_insert_iterator & operator++()
Pre-increment operator.
Definition iterator.h:792
ETL_CONSTEXPR14 front_insert_iterator operator++(int)
Post-increment operator.
Definition iterator.h:800
ETL_NODISCARD ETL_CONSTEXPR14 front_insert_iterator & operator*()
Dereference operator.
Definition iterator.h:784
ETL_CONSTEXPR14 front_insert_iterator & operator=(const typename TContainer::value_type &value)
Assignment operator.
Definition iterator.h:764
Turns assignment into a push.
Definition iterator.h:828
ETL_NODISCARD ETL_CONSTEXPR14 push_insert_iterator & operator*()
Dereference operator.
Definition iterator.h:866
ETL_CONSTEXPR14 push_insert_iterator & operator=(const typename TContainer::value_type &value)
Assignment operator.
Definition iterator.h:844
ETL_CONSTEXPR14 push_insert_iterator & operator++()
Pre-increment operator.
Definition iterator.h:874
ETL_CONSTEXPR14 push_insert_iterator(TContainer &c)
Constructor.
Definition iterator.h:836
ETL_CONSTEXPR14 push_insert_iterator operator++(int)
Post-increment operator.
Definition iterator.h:882
Definition iterator.h:310
Definition array.h:85
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1078
ETL_CONSTEXPR TContainer::pointer data(TContainer &container)
Definition iterator.h:1470
ETL_CONSTEXPR14 etl::circular_iterator< TIterator > operator-(etl::circular_iterator< TIterator > &lhs, typename etl::iterator_traits< TIterator >::difference_type offset)
Definition circular_iterator.h:675
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1130
ETL_NODISCARD ETL_CONSTEXPR14 etl::push_insert_iterator< TContainer > push_inserter(TContainer &container)
Creates a push_insert_iterator from a container.
Definition iterator.h:896
TContainer::const_iterator cbegin(const TContainer &container)
Definition iterator.h:1156
ETL_NODISCARD ETL_CONSTEXPR14 etl::front_insert_iterator< TContainer > front_inserter(TContainer &container)
Creates a front_insert_iterator from a container.
Definition iterator.h:814
char(& array_size(T(&array)[Array_Size]))[Array_Size]
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1144
TContainer::reverse_iterator rend(TContainer &container)
Definition iterator.h:1360
TContainer::const_reverse_iterator crbegin(const TContainer &container)
Definition iterator.h:1350
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
ETL_NODISCARD ETL_CONSTEXPR14 etl::back_insert_iterator< TContainer > back_inserter(TContainer &container)
Creates a back_insert_iterator from a container.
Definition iterator.h:734
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1434
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:541
TContainer::iterator end(TContainer &container)
Definition iterator.h:1166
ETL_CONSTEXPR14 etl::circular_iterator< TIterator > operator+(etl::circular_iterator< TIterator > &lhs, typename etl::iterator_traits< TIterator >::difference_type offset)
Definition circular_iterator.h:662
TContainer::const_reverse_iterator crend(const TContainer &container)
Definition iterator.h:1380
TContainer::const_iterator cend(const TContainer &container)
Definition iterator.h:1186
TContainer::iterator begin(TContainer &container)
Definition iterator.h:1136
TContainer::reverse_iterator rbegin(TContainer &container)
Definition iterator.h:1330
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
Definition iterator.h:61
Definition iterator.h:58
Definition iterator.h:52
Definition iterator.h:933
Definition iterator.h:983
Definition iterator.h:924
Definition iterator.h:961
Definition iterator.h:906
Definition iterator.h:972
Definition iterator.h:915
Definition iterator.h:1014
Definition iterator.h:952
Definition iterator.h:1003
Definition iterator.h:943
Definition iterator.h:130
iterator
Definition iterator.h:482
Definition iterator.h:55
Definition iterator.h:64