Embedded Template Library 1.0
Loading...
Searching...
No Matches
ranges.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) 2026 BMW AG
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_RANGES_INCLUDED
32#define ETL_RANGES_INCLUDED
33
34#include "platform.h"
35
36#include "error_handler.h"
37#include "invoke.h"
38#include "iterator.h"
39#include "limits.h"
40#include "tuple.h"
41#include "type_traits.h"
43
44#if ETL_USING_CPP17
45
46namespace etl
47{
48 namespace ranges
49 {
50 //*************************************************************************
52 //*************************************************************************
53
54 namespace private_ranges
55 {
56 template <typename T, typename Enable = void>
57 struct iterator_trait;
58
59 template <typename T>
60 struct iterator_trait<T, etl::enable_if_t<etl::is_class_v<T>>>
61 {
62 using iterator = typename etl::conditional_t< etl::is_const_v<T>, typename T::const_iterator, typename T::iterator>;
63 using const_iterator = typename T::const_iterator;
64
65 using value_type = typename etl::iterator_traits<const_iterator>::value_type;
66 using difference_type = typename etl::iterator_traits<const_iterator>::difference_type;
67 using pointer = typename etl::iterator_traits<const_iterator>::pointer;
68 using reference = typename etl::iterator_traits<const_iterator>::reference;
69 };
70
71 template <typename T>
72 struct iterator_trait< T, etl::enable_if_t<etl::is_reference_v<T> && !etl::is_array_v<etl::remove_reference_t<T>>>>
73 {
74 using iterator =
75 typename etl::conditional_t< etl::is_const_v<etl::remove_reference_t<T>>, typename etl::remove_reference<T>::type::const_iterator,
76 typename etl::remove_reference<T>::type::iterator>;
77 using const_iterator = typename etl::remove_reference<T>::type::const_iterator;
78
79 using value_type = typename etl::iterator_traits<iterator>::value_type;
80 using difference_type = typename etl::iterator_traits<iterator>::difference_type;
81 using pointer = typename etl::iterator_traits<iterator>::pointer;
82 using reference = typename etl::iterator_traits<iterator>::reference;
83 };
84
85 template <typename T>
86 struct iterator_trait< T, etl::enable_if_t<etl::is_array_v<etl::remove_reference_t<T>>>>
87 {
88 using value_type = typename etl::remove_all_extents<etl::remove_reference_t<T>>::type;
89 using iterator = value_type*;
90 using const_iterator = const value_type*;
91 using difference_type = ptrdiff_t;
92 using pointer = const value_type*;
93 using reference = const value_type&;
94 };
95 } // namespace private_ranges
96
97 template <class D>
98 class view_interface
99 {
100 public:
101
102 view_interface() = default;
103
104 constexpr bool empty() const
105 {
106 return cbegin() == cend();
107 }
108
109 auto cbegin() const
110 {
111 return static_cast<const D*>(this)->begin();
112 }
113
114 auto cend() const
115 {
116 return static_cast<const D*>(this)->end();
117 }
118
119 operator bool() const
120 {
121 return !empty();
122 }
123
124 size_t size() const
125 {
126 return static_cast<size_t>(etl::distance(cbegin(), cend()));
127 }
128
129 constexpr decltype(auto) front()
130 {
131 return *(static_cast<D*>(this)->begin());
132 }
133
134 constexpr decltype(auto) front() const
135 {
136 return *cbegin();
137 }
138
139 template < typename D2 = D,
140 etl::enable_if_t< etl::is_bidirectional_iterator_concept< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
141 constexpr decltype(auto) back()
142 {
143 return *(static_cast<D*>(this)->end() - 1);
144 }
145
146 template < typename D2 = D,
147 etl::enable_if_t< etl::is_bidirectional_iterator_concept< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
148 constexpr decltype(auto) back() const
149 {
150 return *etl::prev(cend());
151 }
152
153 constexpr decltype(auto) operator[](size_t i)
154 {
155 auto it{static_cast<D*>(this)->begin()};
156 etl::advance(it, i);
157 return *it;
158 }
159
160 template < typename D2 = D, etl::enable_if_t<etl::is_random_access_iterator< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
161 constexpr decltype(auto) operator[](size_t i)
162 {
163 return static_cast<D*>(this)->begin()[i];
164 }
165
166 template < typename D2 = D, etl::enable_if_t<etl::is_random_access_iterator< decltype(etl::declval<const D2&>().begin())>::value, int> = 0>
167 constexpr decltype(auto) operator[](size_t i) const
168 {
169 return cbegin()[i];
170 }
171 };
172
173 template <class I>
174 class range_iterator
175 {
176 public:
177
178 auto get() const
179 {
180 return **(static_cast<const I*>(this));
181 }
182 };
183
184 template <class I, class S = I>
185 class subrange : public etl::ranges::view_interface<subrange<I, S>>
186 {
187 public:
188
189 subrange(I i, S s)
190 : _begin{i}
191 , _end{s}
192 {
193 }
194
195 constexpr I begin() const
196 {
197 return _begin;
198 }
199
200 constexpr S end() const
201 {
202 return _end;
203 }
204
205 constexpr subrange& advance(etl::iter_difference_t<I> n)
206 {
207 etl::advance(_begin, n);
208 return *this;
209 }
210
211 constexpr subrange prev(etl::iter_difference_t<I> n = 1)
212 {
213 auto result = subrange{_begin, _end};
214 result.advance(-n);
215 return result;
216 }
217
218 constexpr subrange next(etl::iter_difference_t<I> n = 1)
219 {
220 auto result = subrange{_begin, _end};
221 result.advance(n);
222 return result;
223 }
224
225 private:
226
227 I _begin;
228 S _end;
229 };
230
231 template <class I, class S>
232 subrange(I, S) -> subrange<I, S>;
233
234 template <class T>
235 class empty_view : public etl::ranges::view_interface<empty_view<T>>
236 {
237 public:
238
239 using iterator = T*;
240
241 constexpr empty_view() = default;
242
243 static constexpr iterator begin() noexcept
244 {
245 return nullptr;
246 }
247
248 static constexpr iterator end() noexcept
249 {
250 return nullptr;
251 }
252
253 static constexpr T* data() noexcept
254 {
255 return nullptr;
256 }
257
258 static constexpr size_t size() noexcept
259 {
260 return 0;
261 }
262
263 static constexpr bool empty() noexcept
264 {
265 return true;
266 }
267 };
268
269 struct dangling
270 {
271 constexpr dangling() noexcept = default;
272
273 template <class... Args>
274 constexpr dangling(Args&&...) noexcept
275 {
276 }
277 };
278
279 template <class T>
280 constexpr bool enable_borrowed_range = false;
281
282 template <class T>
283 struct is_borrowed_range
284 {
285 static constexpr bool value = etl::is_range_v<T> || etl::ranges::enable_borrowed_range<T>;
286 };
287
288 template <typename T>
289 inline constexpr bool is_borrowed_range_v = is_borrowed_range<T>::value;
290
291 template <class T>
292 using borrowed_iterator_t = etl::conditional_t<etl::ranges::is_borrowed_range_v<T>, etl::ranges::iterator_t<T>, etl::ranges::dangling>;
293
294 template <class T>
295 using borrowed_subrange_t =
296 etl::conditional_t<etl::ranges::is_borrowed_range_v<T>, etl::ranges::subrange<etl::ranges::iterator_t<T>>, etl::ranges::dangling>;
297
298 namespace views
299 {
300 template <class T>
301 constexpr empty_view<T> empty{};
302 }
303
304 template <class T>
305 class single_view : public etl::ranges::view_interface<single_view<T>>
306 {
307 public:
308
309 using value_type = T;
310 using iterator = value_type*;
311 using const_iterator = const value_type*;
312
313 constexpr single_view(const T& t) noexcept
314 : _value(t)
315 {
316 }
317
318 constexpr single_view(T&& t) noexcept
319 : _value(etl::move(t))
320 {
321 }
322
323 constexpr single_view(const single_view<T>& other)
324 : _value(other._value)
325 {
326 }
327
328 constexpr single_view(single_view<T>&& other)
329 : _value(etl::move(other._value))
330 {
331 }
332
333 constexpr single_view& operator=(const single_view<T>& other)
334 {
335 _value = other._value;
336 return *this;
337 }
338
339 constexpr single_view& operator=(single_view<T>&& other)
340 {
341 _value = etl::move(other._value);
342 return *this;
343 }
344
345 constexpr iterator begin() noexcept
346 {
347 return data();
348 }
349
350 constexpr const_iterator begin() const noexcept
351 {
352 return data();
353 }
354
355 constexpr iterator end() noexcept
356 {
357 return data() + 1;
358 }
359
360 constexpr const_iterator end() const noexcept
361 {
362 return data() + 1;
363 }
364
365 constexpr const T* data() const noexcept
366 {
367 return &_value;
368 }
369
370 constexpr T* data() noexcept
371 {
372 return &_value;
373 }
374
375 constexpr size_t size() const noexcept
376 {
377 return 1;
378 }
379
380 constexpr bool empty() const noexcept
381 {
382 return false;
383 }
384
385 private:
386
387 value_type _value;
388 };
389
390 template <class T>
391 single_view(T) -> single_view<T>;
392
393 namespace views
394 {
395 namespace private_views
396 {
397 struct single
398 {
399 template <typename T>
400 constexpr auto operator()(T&& t) const
401 {
402 return etl::ranges::single_view(t);
403 }
404 };
405 } // namespace private_views
406
407 inline constexpr private_views::single single;
408 } // namespace views
409
410 template <typename T>
411 struct iota_iterator : public range_iterator<iota_iterator<T>>
412 {
413 public:
414
415 using value_type = T;
416 using difference_type = ptrdiff_t;
417 using pointer = T*;
418 using reference = T&;
419
420 using iterator_category = ETL_OR_STD::random_access_iterator_tag;
421
422 constexpr explicit iota_iterator(T i)
423 : _i{i}
424 {
425 }
426
427 constexpr iota_iterator(const iota_iterator& other)
428 : _i{other._i}
429 {
430 }
431
432 iota_iterator& operator++()
433 {
434 ++_i;
435 return *this;
436 }
437
438 iota_iterator operator++(int)
439 {
440 iota_iterator tmp = *this;
441 _i++;
442 return tmp;
443 }
444
445 iota_iterator& operator--()
446 {
447 --_i;
448 return *this;
449 }
450
451 iota_iterator operator--(int)
452 {
453 iota_iterator tmp = *this;
454 _i--;
455 return tmp;
456 }
457
458 iota_iterator& operator+=(difference_type n)
459 {
460 _i += n;
461 return *this;
462 }
463
464 iota_iterator operator+(difference_type n) const
465 {
466 return iota_iterator{static_cast<value_type>(_i + n)};
467 }
468
469 iota_iterator operator-(difference_type n) const
470 {
471 return iota_iterator{static_cast<value_type>(_i - n)};
472 }
473
474 difference_type operator-(iota_iterator other) const
475 {
476 return _i - other._i;
477 }
478
479 iota_iterator& operator=(const iota_iterator& other)
480 {
481 _i = other._i;
482 return *this;
483 }
484
485 constexpr bool operator==(const iota_iterator& other) const
486 {
487 return _i == other._i;
488 }
489
490 constexpr bool operator!=(const iota_iterator& other) const
491 {
492 return _i != other._i;
493 }
494
495 constexpr value_type operator*() const
496 {
497 return _i;
498 }
499
500 constexpr value_type operator*()
501 {
502 return _i;
503 }
504
505 private:
506
507 value_type _i;
508 };
509
510 template <class T>
511 class iota_view : public etl::ranges::view_interface<iota_view<T>>
512 {
513 public:
514
515 using iterator = iota_iterator<T>;
516 using const_iterator = iota_iterator<T>;
517
518 iota_view() = default;
519
520 constexpr explicit iota_view(T value, T bound = etl::numeric_limits<T>::max())
521 : _value(value)
522 , _bound(bound)
523 {
524 }
525
526 constexpr iterator begin() const noexcept
527 {
528 return iterator(_value);
529 }
530
531 constexpr iterator end() const noexcept
532 {
533 return iterator(_bound);
534 }
535
536 constexpr size_t size() const noexcept
537 {
538 if (_bound == etl::numeric_limits<T>::max())
539 {
540 return etl::numeric_limits<T>::max();
541 }
542 return static_cast<size_t>(_bound - _value);
543 }
544
545 constexpr bool empty() const noexcept
546 {
547 return _value == _bound;
548 }
549
550 private:
551
552 T _value;
553 T _bound;
554 };
555
556 template <class T>
557 iota_view(T) -> iota_view<T>;
558
559 namespace views
560 {
561 namespace private_views
562 {
563 struct iota
564 {
565 template <typename T, typename B>
566 constexpr auto operator()(T&& t, B&& b) const
567 {
568 return etl::ranges::iota_view(t, b);
569 }
570 };
571 } // namespace private_views
572
573 inline constexpr private_views::iota iota;
574 } // namespace views
575
576 template <typename T, typename B = T>
577 struct repeat_iterator : public range_iterator<repeat_iterator<T, B>>
578 {
579 public:
580
581 using value_type = T;
582 using difference_type = ptrdiff_t;
583 using pointer = T*;
584 using reference = T&;
585
586 using iterator_category = ETL_OR_STD::random_access_iterator_tag;
587
588 constexpr repeat_iterator()
589 : _value{}
590 , _i{}
591 {
592 }
593
594 constexpr explicit repeat_iterator(T value, B i = etl::numeric_limits<B>::max())
595 : _value{value}
596 , _i{i}
597 {
598 }
599
600 constexpr repeat_iterator(const repeat_iterator& other) = default;
601
602 repeat_iterator& operator++()
603 {
604 --_i;
605 return *this;
606 }
607
608 repeat_iterator operator++(int)
609 {
610 repeat_iterator tmp(*this);
611 _i--;
612 return tmp;
613 }
614
615 repeat_iterator& operator--()
616 {
617 ++_i;
618 return *this;
619 }
620
621 repeat_iterator operator--(int)
622 {
623 repeat_iterator tmp(*this);
624 _i++;
625 return tmp;
626 }
627
628 repeat_iterator& operator+=(difference_type n)
629 {
630 _i -= static_cast<B>(n);
631 return *this;
632 }
633
634 repeat_iterator operator+(difference_type n) const
635 {
636 return repeat_iterator{_value, static_cast<B>(_i - static_cast<B>(n))};
637 }
638
639 repeat_iterator operator-(difference_type n) const
640 {
641 return repeat_iterator{_value, static_cast<B>(_i + static_cast<B>(n))};
642 }
643
644 difference_type operator-(repeat_iterator other) const
645 {
646 return other._i - _i;
647 }
648
649 repeat_iterator& operator=(const repeat_iterator& other)
650 {
651 _i = other._i;
652 _value = other._value;
653 return *this;
654 }
655
656 constexpr bool operator==(const repeat_iterator& other) const
657 {
658 return _i == other._i;
659 }
660
661 constexpr bool operator!=(const repeat_iterator& other) const
662 {
663 return _i != other._i;
664 }
665
666 constexpr value_type operator*() const
667 {
668 return _value;
669 }
670
671 constexpr value_type operator*()
672 {
673 return _value;
674 }
675
676 private:
677
678 value_type _value;
679 B _i;
680 };
681
682 template <class T, class B = T>
683 class repeat_view : public etl::ranges::view_interface<repeat_view<T>>
684 {
685 public:
686
687 using iterator = repeat_iterator<T, B>;
688 using const_iterator = repeat_iterator<T, B>;
689
690 repeat_view() = default;
691
692 constexpr explicit repeat_view(T value, B bound = etl::numeric_limits<B>::max())
693 : _value(value)
694 , _bound(bound)
695 {
696 }
697
698 constexpr iterator begin() const noexcept
699 {
700 return iterator(_value, _bound);
701 }
702
703 constexpr iterator end() const noexcept
704 {
705 return iterator(_value, 0);
706 }
707
708 constexpr size_t size() const noexcept
709 {
710 return static_cast<size_t>(_bound);
711 }
712
713 constexpr bool empty() const noexcept
714 {
715 return _bound == 0;
716 }
717
718 private:
719
720 T _value;
721 B _bound;
722 };
723
724 template <class T, class B = T>
725 repeat_view(T, B = B()) -> repeat_view<T, B>;
726
727 namespace views
728 {
729 namespace private_views
730 {
731 struct repeat
732 {
733 template <typename T, typename B>
734 constexpr auto operator()(T&& t, B&& b) const
735 {
736 return etl::ranges::repeat_view(t, b);
737 }
738 };
739 } // namespace private_views
740
741 inline constexpr private_views::repeat repeat;
742 } // namespace views
743
744 // Non-template base so ADL finds exactly one operator| definition.
745 class range_adapter_closure_base
746 {
747 // Found via ADL on the RHS (any type that derives from
748 // range_adapter_closure_base). Placing the operator here instead of at
749 // global/namespace scope avoids conflicts with std::ranges::operator|.
750 template <class Range, class Closure,
751 typename = etl::enable_if_t< etl::is_base_of_v<range_adapter_closure_base, etl::decay_t<Closure>>
752 && etl::is_invocable_v<etl::decay_t<Closure>, Range>>>
753 friend auto operator|(Range&& r, Closure&& c)
754 {
755 return etl::forward<Closure>(c)(etl::forward<Range>(r));
756 }
757 };
758
759 template <class Derived>
760 class range_adapter_closure : public range_adapter_closure_base
761 {
762 };
763
764 template <class Range>
765 class ref_view : public etl::ranges::view_interface<ref_view<Range>>
766 {
767 public:
768
769 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
770 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
771 using pointer = typename etl::ranges::private_ranges::iterator_trait<Range>::pointer;
772
773 ref_view(Range& r)
774 : _r{&r}
775 {
776 }
777
778 constexpr Range& base() const
779 {
780 return *_r;
781 }
782
783 constexpr iterator begin() const
784 {
785 return iterator(ETL_OR_STD::begin(*_r));
786 }
787
788 constexpr iterator end() const
789 {
790 return iterator(ETL_OR_STD::end(*_r));
791 }
792
793 constexpr bool empty() const
794 {
795 return begin() == end();
796 }
797
798 constexpr size_t size() const
799 {
800 return static_cast<size_t>(etl::distance(begin(), end()));
801 }
802
803 constexpr pointer data() const
804 {
805 return &(*begin());
806 }
807
808 private:
809
810 Range* _r;
811 };
812
813 template <class Range>
814 ref_view(Range&) -> ref_view<Range>;
815
816 struct ref_range_adapter_closure : public range_adapter_closure<ref_range_adapter_closure>
817 {
818 template <typename Range>
819 using target_view_type = ref_view<Range>;
820
821 ref_range_adapter_closure() = default;
822
823 template <typename Range>
824 ref_view<Range> operator()(Range& r)
825 {
826 return ref_view<Range>(r);
827 }
828 };
829
830 namespace views
831 {
832 namespace private_views
833 {
834 struct ref
835 {
836 template <class Range>
837 constexpr auto operator()(Range& r) const
838 {
839 return ranges::ref_view(r);
840 }
841
842 constexpr auto operator()() const
843 {
844 return ranges::ref_range_adapter_closure();
845 }
846 };
847 } // namespace private_views
848
849 inline constexpr private_views::ref ref;
850 } // namespace views
851
852 template <class Range>
853 class owning_view : public etl::ranges::view_interface<owning_view<Range>>
854 {
855 public:
856
857 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
858 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
859 using pointer = typename etl::ranges::private_ranges::iterator_trait<Range>::pointer;
860
861 owning_view() = default;
862
863 owning_view(owning_view&& other) = default;
864
865 constexpr owning_view(Range&& r)
866 : _r(etl::move(r))
867 {
868 }
869
870 owning_view& operator=(const owning_view&) = delete;
871
872 owning_view& operator=(owning_view&& other)
873 {
874 _r = etl::move(other._r);
875 return *this;
876 }
877
878 constexpr Range& base() noexcept
879 {
880 return _r;
881 }
882
883 constexpr iterator begin() const
884 {
885 return iterator(ETL_OR_STD::begin(_r));
886 }
887
888 constexpr iterator end() const
889 {
890 return iterator(ETL_OR_STD::end(_r));
891 }
892
893 constexpr bool empty() const
894 {
895 return begin() == end();
896 }
897
898 constexpr size_t size() const
899 {
900 return static_cast<size_t>(etl::distance(begin(), end()));
901 }
902
903 constexpr pointer data()
904 {
905 return &(*begin());
906 }
907
908 private:
909
910 // 'mutable' so that the const begin()/end() observe a non-const '_r' and
911 // therefore call the non-const ETL_OR_STD::begin/end overloads, yielding
912 // the (mutable) 'iterator' rather than a 'const_iterator' that cannot be
913 // converted back to 'iterator'.
914 mutable Range _r;
915 };
916
917 template <class Range>
918 owning_view(Range&&) -> owning_view<Range>;
919
920 struct owning_range_adapter_closure : public range_adapter_closure<owning_range_adapter_closure>
921 {
922 template <typename Range, typename CleanRange = etl::remove_reference_t<Range>>
923 using target_view_type = owning_view<CleanRange>;
924
925 owning_range_adapter_closure() = default;
926
927 template <typename Range, typename CleanRange = etl::remove_reference_t<Range>>
928 owning_view<CleanRange> operator()(Range&& r)
929 {
930 return owning_view<CleanRange>(etl::move(r));
931 }
932 };
933
934 namespace views
935 {
936 namespace private_views
937 {
938 struct owning
939 {
940 template <class Range>
941 constexpr auto operator()(Range&& r) const
942 {
943 return ranges::owning_view(etl::forward<Range>(r));
944 }
945
946 constexpr auto operator()() const
947 {
948 return ranges::owning_range_adapter_closure();
949 }
950 };
951 } // namespace private_views
952
953 inline constexpr private_views::owning owning;
954 } // namespace views
955
956 namespace views
957 {
958 namespace private_views
959 {
960 struct all : public range_adapter_closure_base
961 {
962 template < class Range,
963 etl::enable_if_t<etl::is_base_of_v< etl::ranges::view_interface<etl::decay_t<Range>>, etl::decay_t<Range>>, int> = 0>
964 constexpr etl::decay_t<Range> operator()(Range&& r) const
965 {
966 return r;
967 }
968
969 template < class Range,
970 etl::enable_if_t<!etl::is_base_of_v< etl::ranges::view_interface<etl::decay_t<Range>>, etl::decay_t<Range>>, int> = 0>
971 constexpr auto operator()(Range&& r) const
972 {
973 if constexpr (etl::is_lvalue_reference_v<Range>)
974 {
975 return etl::ranges::ref_view(etl::forward<Range>(r));
976 }
977 else
978 {
979 return etl::ranges::owning_view(etl::forward<Range>(r));
980 }
981 }
982 };
983 } // namespace private_views
984
985 inline constexpr private_views::all all;
986
987 template <typename R>
988 using all_t = decltype(views::all(etl::declval<R>()));
989 } // namespace views
990
991 template <class Range, class Pred>
992 class filter_iterator
993 {
994 public:
995
996 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
997
998 using iterator = typename trait::iterator;
999 using const_iterator = typename trait::const_iterator;
1000 using value_type = typename trait::value_type;
1001 using difference_type = typename trait::difference_type;
1002 // Derive the reference from the mutable iterator so filtered elements
1003 // remain mutable when the underlying range is non-const, as required for
1004 // std::ranges::filter_view.
1005 using reference = decltype(*etl::declval<iterator&>());
1006 using pointer = etl::remove_reference_t<reference>*;
1007
1008 using iterator_category = ETL_OR_STD::bidirectional_iterator_tag;
1009
1010 filter_iterator(iterator it, iterator it_end, const Pred& p)
1011 : _it{it}
1012 , _it_begin{it}
1013 , _it_end{it_end}
1014 , _p{p}
1015 {
1016 while (_it != _it_end && !_p(*_it))
1017 {
1018 ++_it;
1019 }
1020 }
1021
1022 filter_iterator(const filter_iterator& other)
1023 : _it{other._it}
1024 , _it_begin{other._it_begin}
1025 , _it_end{other._it_end}
1026 , _p{other._p}
1027 {
1028 while (_it != _it_end && !_p(*_it))
1029 {
1030 ++_it;
1031 }
1032 }
1033
1034 filter_iterator& operator++()
1035 {
1036 ++_it;
1037 while (_it != _it_end && !_p(*_it))
1038 {
1039 ++_it;
1040 }
1041 return *this;
1042 }
1043
1044 filter_iterator operator++(int)
1045 {
1046 filter_iterator tmp = *this;
1047
1048 _it++;
1049 while (_it != _it_end && !_p(*_it))
1050 {
1051 _it++;
1052 }
1053
1054 return tmp;
1055 }
1056
1057 filter_iterator& operator--()
1058 {
1059 --_it;
1060 while (_it != _it_begin && !_p(*_it))
1061 {
1062 --_it;
1063 }
1064 return *this;
1065 }
1066
1067 filter_iterator operator--(int)
1068 {
1069 filter_iterator tmp = *this;
1070
1071 _it--;
1072 while (_it != _it_begin && !_p(*_it))
1073 {
1074 _it--;
1075 }
1076
1077 return tmp;
1078 }
1079
1080 filter_iterator& operator+=(size_t n)
1081 {
1082 for (size_t i = 0; i < n; i++)
1083 {
1084 if (_it != _it_end)
1085 {
1086 ++(*this);
1087 }
1088 }
1089
1090 return *this;
1091 }
1092
1093 filter_iterator& operator-=(size_t n)
1094 {
1095 for (size_t i = 0; i < n; i++)
1096 {
1097 if (_it != _it_begin)
1098 {
1099 --(*this);
1100 }
1101 }
1102
1103 return *this;
1104 }
1105
1106 filter_iterator& operator=(const filter_iterator& other)
1107 {
1108 _it = other._it;
1109 _it_begin = other._it_begin;
1110 _it_end = other._it_end;
1111 ETL_ASSERT(&_p == &other._p, ETL_ERROR_GENERIC("Predicates need to be the same"));
1112 return *this;
1113 }
1114
1115 reference operator*()
1116 {
1117 return *_it;
1118 }
1119
1120 bool operator==(const filter_iterator& other) const
1121 {
1122 return other._it == _it;
1123 }
1124
1125 bool operator!=(const filter_iterator& other) const
1126 {
1127 return !(*this == other);
1128 }
1129
1130 private:
1131
1132 iterator _it;
1133 iterator _it_begin;
1134 iterator _it_end;
1135 const Pred& _p;
1136 };
1137
1138 template <class Range, class Pred>
1139 constexpr typename filter_iterator<Range, Pred>::difference_type operator-(const filter_iterator<Range, Pred>& lhs,
1140 const filter_iterator<Range, Pred>& rhs)
1141 {
1142 typename filter_iterator<Range, Pred>::difference_type result{0};
1143 filter_iterator<Range, Pred> it_up{rhs};
1144 while (it_up != lhs)
1145 {
1146 ++it_up;
1147 ++result;
1148 }
1149 return result;
1150 }
1151
1152 template <class Range, typename Pred>
1153 class filter_view : public etl::ranges::view_interface<filter_view<Range, Pred>>
1154 {
1155 public:
1156
1157 using iterator = filter_iterator<Range, Pred>;
1158 using const_iterator = filter_iterator<Range, Pred>;
1159
1160 filter_view(Range&& r, const Pred& pred)
1161 : _pred{pred}
1162 , _r{etl::move(r)}
1163 {
1164 }
1165
1166 constexpr Range& base() const&
1167 {
1168 return _r;
1169 }
1170
1171 constexpr const Pred& pred() const
1172 {
1173 return _pred;
1174 }
1175
1176 constexpr const_iterator begin() const
1177 {
1178 return const_iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pred);
1179 }
1180
1181 constexpr const_iterator end() const
1182 {
1183 return const_iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pred);
1184 }
1185
1186 private:
1187
1188 const Pred _pred;
1189 mutable Range _r;
1190 };
1191
1192 template <class Range, typename Pred>
1193 filter_view(Range&&, Pred) -> filter_view<views::all_t<Range>, Pred>;
1194
1195 template <typename Pred>
1196 struct filter_range_adapter_closure : public range_adapter_closure<filter_range_adapter_closure<Pred>>
1197 {
1198 template <typename Range>
1199 using target_view_type = filter_view<Range, Pred>;
1200
1201 filter_range_adapter_closure(const Pred& p)
1202 : _p{p}
1203 {
1204 }
1205
1206 template <typename Range>
1207 constexpr auto operator()(Range&& r)
1208 {
1209 return filter_view(views::all(etl::forward<Range>(r)), _p);
1210 }
1211
1212 const Pred _p;
1213 };
1214
1215 namespace views
1216 {
1217 namespace private_views
1218 {
1219 struct filter
1220 {
1221 template <class Range, typename Pred>
1222 constexpr auto operator()(Range&& r, const Pred& p) const
1223 {
1224 return filter_view(views::all(etl::forward<Range>(r)), p);
1225 }
1226
1227 template <typename Pred>
1228 constexpr auto operator()(const Pred& p) const
1229 {
1230 return ranges::filter_range_adapter_closure<Pred>(p);
1231 }
1232 };
1233 } // namespace private_views
1234
1235 inline constexpr private_views::filter filter;
1236 } // namespace views
1237
1238 template <class Range, class Fun>
1239 class transform_iterator
1240 {
1241 public:
1242
1243 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
1244
1245 using iterator = typename trait::iterator;
1246 using const_iterator = typename trait::const_iterator;
1247 using difference_type = typename trait::difference_type;
1248
1249 // transform_view is type-changing: the element type is the result of applying
1250 // the transform function to the underlying element, not the underlying range's
1251 // element type (as specified for std::ranges::transform_view).
1252 using reference = decltype(etl::declval<const Fun&>()(*etl::declval<const_iterator&>()));
1253 using value_type = etl::remove_cvref_t<reference>;
1254 using pointer = void;
1255
1256 using iterator_category = ETL_OR_STD::forward_iterator_tag;
1257
1258 transform_iterator(const_iterator it, const Fun& f)
1259 : _it(it)
1260 , _f(f)
1261 {
1262 }
1263
1264 transform_iterator(const transform_iterator& other)
1265 : _it{other._it}
1266 , _f{other._f}
1267 {
1268 }
1269
1270 transform_iterator& operator++()
1271 {
1272 ++_it;
1273 return *this;
1274 }
1275
1276 transform_iterator operator++(int)
1277 {
1278 transform_iterator tmp = *this;
1279 _it++;
1280 return tmp;
1281 }
1282
1283 transform_iterator& operator=(const transform_iterator& other)
1284 {
1285 _it = other._it;
1286 ETL_ASSERT(&_f == &other._f, ETL_ERROR_GENERIC("Transform functions need to be the same"));
1287 return *this;
1288 }
1289
1290 reference operator*()
1291 {
1292 return _f(*_it);
1293 }
1294
1295 bool operator==(const transform_iterator& other) const
1296 {
1297 return other._it == _it;
1298 }
1299
1300 bool operator!=(const transform_iterator& other) const
1301 {
1302 return !(*this == other);
1303 }
1304
1305 private:
1306
1307 const_iterator _it;
1308 const Fun& _f;
1309 };
1310
1311 template <class Range, typename Fun>
1312 class transform_view : public etl::ranges::view_interface<transform_view<Range, Fun>>
1313 {
1314 public:
1315
1316 using iterator = transform_iterator<Range, Fun>;
1317 using const_iterator = transform_iterator<Range, Fun>;
1318
1319 transform_view(Range&& r, const Fun& fun)
1320 : _fun{fun}
1321 , _r{etl::move(r)}
1322 {
1323 }
1324
1325 constexpr Range& base() const&
1326 {
1327 return _r;
1328 }
1329
1330 constexpr const_iterator begin() const
1331 {
1332 return const_iterator(ETL_OR_STD::begin(_r), _fun);
1333 }
1334
1335 constexpr const_iterator end() const
1336 {
1337 return const_iterator(ETL_OR_STD::end(_r), _fun);
1338 }
1339
1340 constexpr size_t size() const
1341 {
1342 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1343 }
1344
1345 private:
1346
1347 const Fun _fun;
1348 Range _r;
1349 };
1350
1351 template <class Range, typename Fun>
1352 transform_view(Range&&, Fun) -> transform_view<views::all_t<Range>, Fun>;
1353
1354 template <typename Fun>
1355 struct transform_range_adapter_closure : public range_adapter_closure<transform_range_adapter_closure<Fun>>
1356 {
1357 template <typename Range>
1358 using target_view_type = transform_view<Range, Fun>;
1359
1360 transform_range_adapter_closure(const Fun& f)
1361 : _f{f}
1362 {
1363 }
1364
1365 template <typename Range>
1366 constexpr auto operator()(Range&& r)
1367 {
1368 return transform_view(views::all(etl::forward<Range>(r)), _f);
1369 }
1370
1371 const Fun _f;
1372 };
1373
1374 namespace views
1375 {
1376 namespace private_views
1377 {
1378 struct transform
1379 {
1380 template <class Range, typename Fun>
1381 constexpr auto operator()(Range&& r, const Fun& f) const
1382 {
1383 return transform_view(views::all(etl::forward<Range>(r)), f);
1384 }
1385
1386 template <typename Fun>
1387 constexpr auto operator()(const Fun& f) const
1388 {
1389 return ranges::transform_range_adapter_closure<Fun>(f);
1390 }
1391 };
1392 } // namespace private_views
1393
1394 inline constexpr private_views::transform transform;
1395 } // namespace views
1396
1397 template <class Range>
1398 class as_rvalue_view : public etl::ranges::view_interface<as_rvalue_view<Range>>
1399 {
1400 public:
1401
1402 using iterator = typename etl::move_iterator< typename etl::ranges::private_ranges::iterator_trait<Range>::iterator>;
1403
1404 as_rvalue_view(const as_rvalue_view& other) = default;
1405
1406 as_rvalue_view(Range&& r)
1407 : _r{etl::move(r)}
1408 {
1409 }
1410
1411 constexpr Range& base() const
1412 {
1413 return _r;
1414 }
1415
1416 constexpr iterator begin() const
1417 {
1418 return iterator(ETL_OR_STD::begin(_r));
1419 }
1420
1421 constexpr iterator end() const
1422 {
1423 return iterator(ETL_OR_STD::end(_r));
1424 }
1425
1426 constexpr size_t size() const
1427 {
1428 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1429 }
1430
1431 private:
1432
1433 Range _r;
1434 };
1435
1436 template <class Range>
1437 as_rvalue_view(Range&&) -> as_rvalue_view<views::all_t<Range>>;
1438
1439 struct as_rvalue_range_adapter_closure : public range_adapter_closure<as_rvalue_range_adapter_closure>
1440 {
1441 template <typename Range>
1442 using target_view_type = as_rvalue_view<Range>;
1443
1444 as_rvalue_range_adapter_closure() = default;
1445
1446 template <typename Range>
1447 constexpr auto operator()(Range&& r)
1448 {
1449 return as_rvalue_view(views::all(etl::forward<Range>(r)));
1450 }
1451 };
1452
1453 namespace views
1454 {
1455 namespace private_views
1456 {
1457 struct as_rvalue : public range_adapter_closure_base
1458 {
1459 template <class Range>
1460 constexpr auto operator()(Range&& r) const
1461 {
1462 return as_rvalue_view(views::all(etl::forward<Range>(r)));
1463 }
1464
1465 constexpr auto operator()() const
1466 {
1467 return ranges::as_rvalue_range_adapter_closure();
1468 }
1469 };
1470 } // namespace private_views
1471
1472 inline constexpr private_views::as_rvalue as_rvalue;
1473 } // namespace views
1474
1475 template <class Range>
1476 class as_const_view : public etl::ranges::view_interface<as_const_view<Range>>
1477 {
1478 public:
1479
1480 using iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
1481 using const_iterator = iterator;
1482
1483 as_const_view(const as_const_view& other) = default;
1484
1485 as_const_view(Range&& r)
1486 : _r{etl::move(r)}
1487 {
1488 }
1489
1490 constexpr Range& base() const
1491 {
1492 return _r;
1493 }
1494
1495 constexpr iterator begin() const
1496 {
1497 return ETL_OR_STD::cbegin(_r);
1498 }
1499
1500 constexpr iterator end() const
1501 {
1502 return ETL_OR_STD::cend(_r);
1503 }
1504
1505 constexpr size_t size() const
1506 {
1507 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1508 }
1509
1510 private:
1511
1512 mutable Range _r;
1513 };
1514
1515 template <class Range>
1516 as_const_view(Range&&) -> as_const_view<views::all_t<Range>>;
1517
1518 struct as_const_range_adapter_closure : public range_adapter_closure<as_const_range_adapter_closure>
1519 {
1520 template <typename Range>
1521 using target_view_type = as_const_view<Range>;
1522
1523 as_const_range_adapter_closure() = default;
1524
1525 template <typename Range>
1526 constexpr auto operator()(Range&& r)
1527 {
1528 return as_const_view(views::all(etl::forward<Range>(r)));
1529 }
1530 };
1531
1532 namespace views
1533 {
1534 namespace private_views
1535 {
1536 struct as_const : public range_adapter_closure_base
1537 {
1538 template <class Range>
1539 constexpr auto operator()(Range&& r) const
1540 {
1541 return as_const_view(views::all(etl::forward<Range>(r)));
1542 }
1543
1544 constexpr auto operator()() const
1545 {
1546 return ranges::as_const_range_adapter_closure();
1547 }
1548 };
1549 } // namespace private_views
1550
1551 inline constexpr private_views::as_const as_const;
1552 } // namespace views
1553
1554 //*************************************************************************
1558 //*************************************************************************
1559 namespace private_ranges
1560 {
1561 template <typename T>
1562 struct cache_latest_cache
1563 {
1564 cache_latest_cache()
1565 : _has_value{false}
1566 , _value{}
1567 {
1568 }
1569
1570 cache_latest_cache(const cache_latest_cache&) = delete;
1571 cache_latest_cache& operator=(const cache_latest_cache&) = delete;
1572
1573 bool has_value() const
1574 {
1575 return _has_value;
1576 }
1577
1578 void set(const T& v)
1579 {
1580 _value = v;
1581 _has_value = true;
1582 }
1583
1584 void reset()
1585 {
1586 _has_value = false;
1587 }
1588
1589 T& value()
1590 {
1591 return _value;
1592 }
1593
1594 bool _has_value;
1595 T _value;
1596 };
1597 } // namespace private_ranges
1598
1599 //*************************************************************************
1601 //*************************************************************************
1602 template <class Range>
1603 class cache_latest_iterator
1604 {
1605 public:
1606
1607 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
1608
1609 using iterator = typename trait::iterator;
1610 using const_iterator = typename trait::const_iterator;
1611 using value_type = typename trait::value_type;
1612 using difference_type = typename trait::difference_type;
1613 using pointer = value_type*;
1614 using reference = value_type&;
1615
1616 using iterator_category = ETL_OR_STD::forward_iterator_tag;
1617
1618 cache_latest_iterator() = default;
1619
1620 cache_latest_iterator(const_iterator it, private_ranges::cache_latest_cache<value_type>* cache)
1621 : _it(it)
1622 , _cache(cache)
1623 {
1624 }
1625
1626 cache_latest_iterator(const cache_latest_iterator& other)
1627 : _it(other._it)
1628 , _cache(other._cache)
1629 {
1630 }
1631
1632 cache_latest_iterator& operator++()
1633 {
1634 ++_it;
1635 if (_cache)
1636 {
1637 _cache->reset();
1638 }
1639 return *this;
1640 }
1641
1642 cache_latest_iterator operator++(int)
1643 {
1644 cache_latest_iterator tmp = *this;
1645 ++(*this);
1646 return tmp;
1647 }
1648
1649 cache_latest_iterator& operator=(const cache_latest_iterator& other)
1650 {
1651 _it = other._it;
1652 _cache = other._cache;
1653 return *this;
1654 }
1655
1656 reference operator*() const
1657 {
1658 if (_cache && !_cache->has_value())
1659 {
1660 _cache->set(*_it);
1661 }
1662 return _cache->value();
1663 }
1664
1665 pointer operator->() const
1666 {
1667 return &(**this);
1668 }
1669
1670 bool operator==(const cache_latest_iterator& other) const
1671 {
1672 return other._it == _it;
1673 }
1674
1675 bool operator!=(const cache_latest_iterator& other) const
1676 {
1677 return !(*this == other);
1678 }
1679
1680 private:
1681
1682 mutable const_iterator _it;
1683 private_ranges::cache_latest_cache<value_type>* _cache;
1684 };
1685
1686 //*************************************************************************
1691 //*************************************************************************
1692 template <class Range>
1693 class cache_latest_view : public etl::ranges::view_interface<cache_latest_view<Range>>
1694 {
1695 public:
1696
1697 using iterator = cache_latest_iterator<Range>;
1698 using const_iterator = cache_latest_iterator<Range>;
1699 using value_type = typename etl::ranges::private_ranges::iterator_trait<Range>::value_type;
1700
1701 cache_latest_view(Range&& r)
1702 : _r{etl::move(r)}
1703 , _cache{}
1704 {
1705 }
1706
1707 cache_latest_view(const cache_latest_view& other)
1708 : _r{other._r}
1709 , _cache{}
1710 {
1711 }
1712
1713 constexpr Range& base() const&
1714 {
1715 return _r;
1716 }
1717
1718 constexpr iterator begin() const
1719 {
1720 _cache.reset();
1721 return iterator(ETL_OR_STD::begin(_r), &_cache);
1722 }
1723
1724 constexpr iterator end() const
1725 {
1726 return iterator(ETL_OR_STD::end(_r), &_cache);
1727 }
1728
1729 constexpr size_t size() const
1730 {
1731 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
1732 }
1733
1734 private:
1735
1736 mutable Range _r;
1737 mutable private_ranges::cache_latest_cache<value_type> _cache;
1738 };
1739
1740 template <class Range>
1741 cache_latest_view(Range&&) -> cache_latest_view<views::all_t<Range>>;
1742
1743 struct cache_latest_range_adapter_closure : public range_adapter_closure<cache_latest_range_adapter_closure>
1744 {
1745 template <typename Range>
1746 using target_view_type = cache_latest_view<Range>;
1747
1748 cache_latest_range_adapter_closure() = default;
1749
1750 template <typename Range>
1751 constexpr auto operator()(Range&& r)
1752 {
1753 return cache_latest_view(views::all(etl::forward<Range>(r)));
1754 }
1755 };
1756
1757 namespace views
1758 {
1759 namespace private_views
1760 {
1761 struct cache_latest : public range_adapter_closure_base
1762 {
1763 template <class Range>
1764 constexpr auto operator()(Range&& r) const
1765 {
1766 return cache_latest_view(views::all(etl::forward<Range>(r)));
1767 }
1768
1769 constexpr auto operator()() const
1770 {
1771 return ranges::cache_latest_range_adapter_closure();
1772 }
1773 };
1774 } // namespace private_views
1775
1776 inline constexpr private_views::cache_latest cache_latest;
1777 } // namespace views
1778
1779 template <class Range>
1780 class reverse_view : public etl::ranges::view_interface<reverse_view<Range>>
1781 {
1782 public:
1783
1784 using iterator = ETL_OR_STD::reverse_iterator< typename etl::ranges::private_ranges::iterator_trait<Range>::iterator>;
1785 using const_iterator = ETL_OR_STD::reverse_iterator< typename etl::ranges::private_ranges::iterator_trait<Range>::const_iterator>;
1786 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
1787
1788 constexpr reverse_view(Range&& r)
1789 : _r{etl::move(r)}
1790 {
1791 }
1792
1793 reverse_view(const reverse_view& other) = default;
1794
1795 constexpr Range base() const&
1796 {
1797 return _r;
1798 }
1799
1800 constexpr iterator begin() const
1801 {
1802 return iterator(ETL_OR_STD::end(_r));
1803 }
1804
1805 constexpr iterator end() const
1806 {
1807 return iterator(ETL_OR_STD::begin(_r));
1808 }
1809
1810 constexpr size_t size() const
1811 {
1812 return static_cast<size_t>(etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)));
1813 }
1814
1815 private:
1816
1817 Range _r;
1818 };
1819
1820 template <class Range>
1821 reverse_view(Range&&) -> reverse_view<views::all_t<Range>>;
1822
1823 template <typename T>
1824 struct is_reverse_view : etl::false_type
1825 {
1826 };
1827
1828 template <typename Range>
1829 struct is_reverse_view<reverse_view<Range>> : etl::true_type
1830 {
1831 };
1832
1833 namespace views
1834 {
1835 namespace private_views
1836 {
1837 struct reverse : public range_adapter_closure_base
1838 {
1839 template <class Range>
1840 constexpr auto operator()(Range&& r) const
1841 {
1842 if constexpr (is_reverse_view<etl::remove_cv_t< etl::remove_reference_t<Range>>>::value)
1843 {
1844 return r.base();
1845 }
1846 else
1847 {
1848 return reverse_view(views::all(etl::forward<Range>(r)));
1849 }
1850 }
1851 };
1852 } // namespace private_views
1853
1854 inline constexpr private_views::reverse reverse;
1855 } // namespace views
1856
1857 template <class Range>
1858 class drop_view : public etl::ranges::view_interface<drop_view<Range>>
1859 {
1860 public:
1861
1862 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
1863 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
1864 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
1865
1866 constexpr drop_view(Range&& r, size_t drop_n)
1867 : _r{etl::move(r)}
1868 , _drop_n{drop_n}
1869 , _begin_cache{ETL_OR_STD::end(_r)}
1870 , _begin_cache_valid{false}
1871 {
1872 }
1873
1874 drop_view(const drop_view& other) = default;
1875
1876 constexpr Range base() const&
1877 {
1878 return _r;
1879 }
1880
1881 constexpr iterator begin() const
1882 {
1883 if (!_begin_cache_valid)
1884 {
1885 _begin_cache = drop_begin();
1886 _begin_cache_valid = true;
1887 }
1888 return _begin_cache;
1889 }
1890
1891 constexpr iterator end() const
1892 {
1893 return iterator(ETL_OR_STD::end(_r));
1894 }
1895
1896 constexpr size_t size() const
1897 {
1898 if (!_begin_cache_valid)
1899 {
1900 _begin_cache = drop_begin();
1901 _begin_cache_valid = true;
1902 }
1903 return static_cast<size_t>(etl::distance(_begin_cache, ETL_OR_STD::end(_r)));
1904 }
1905
1906 private:
1907
1908 constexpr iterator drop_begin() const
1909 {
1910 iterator result{ETL_OR_STD::end(_r)};
1911 if (static_cast<difference_type>(_drop_n) < etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)))
1912 {
1913 result = ETL_OR_STD::begin(_r);
1914 etl::advance(result, _drop_n);
1915 }
1916 return result;
1917 }
1918
1919 Range _r;
1920 size_t _drop_n;
1921 mutable iterator _begin_cache;
1922 mutable bool _begin_cache_valid;
1923 };
1924
1925 template <class Range>
1926 drop_view(Range&&) -> drop_view<views::all_t<Range>>;
1927
1928 struct drop_range_adapter_closure : public range_adapter_closure<drop_range_adapter_closure>
1929 {
1930 template <typename Range>
1931 using target_view_type = drop_view<Range>;
1932
1933 constexpr drop_range_adapter_closure(size_t drop_n)
1934 : _drop_n{drop_n}
1935 {
1936 }
1937
1938 template <typename Range>
1939 constexpr auto operator()(Range&& r) const
1940 {
1941 return drop_view(views::all(etl::forward<Range>(r)), _drop_n);
1942 }
1943
1944 const size_t _drop_n;
1945 };
1946
1947 namespace views
1948 {
1949 namespace private_views
1950 {
1951 struct drop
1952 {
1953 template <class Range>
1954 constexpr auto operator()(Range&& r, size_t drop_n) const
1955 {
1956 return drop_view(views::all(etl::forward<Range>(r)), drop_n);
1957 }
1958
1959 constexpr auto operator()(size_t drop_n) const
1960 {
1961 return ranges::drop_range_adapter_closure(drop_n);
1962 }
1963 };
1964 } // namespace private_views
1965
1966 inline constexpr private_views::drop drop;
1967 } // namespace views
1968
1969 template <class Range, class Pred>
1970 class drop_while_view : public etl::ranges::view_interface<drop_while_view<Range, Pred>>
1971 {
1972 public:
1973
1974 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
1975 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
1976
1977 constexpr drop_while_view(Range&& r, Pred pred)
1978 : _r{etl::move(r)}
1979 , _pred{pred}
1980 , _begin_cache{}
1981 , _begin_cache_valid{false}
1982 {
1983 }
1984
1985 constexpr const Range base() const&
1986 {
1987 return _r;
1988 }
1989
1990 constexpr const Pred& pred() const
1991 {
1992 return _pred;
1993 }
1994
1995 constexpr const_iterator begin() const
1996 {
1997 if (!_begin_cache_valid)
1998 {
1999 const_iterator result{ETL_OR_STD::cbegin(_r)};
2000 while (result != ETL_OR_STD::cend(_r) && _pred(*result))
2001 {
2002 ++result;
2003 }
2004 _begin_cache = result;
2005 _begin_cache_valid = true;
2006 }
2007 return _begin_cache;
2008 }
2009
2010 constexpr const_iterator end() const
2011 {
2012 return const_iterator(ETL_OR_STD::cend(_r));
2013 }
2014
2015 private:
2016
2017 Range _r;
2018 Pred _pred;
2019 mutable const_iterator _begin_cache;
2020 mutable bool _begin_cache_valid;
2021 };
2022
2023 template <class Range, class Pred>
2024 drop_while_view(Range&&, Pred) -> drop_while_view<views::all_t<Range>, Pred>;
2025
2026 template <typename Pred>
2027 struct drop_while_range_adapter_closure : public range_adapter_closure<drop_while_range_adapter_closure<Pred>>
2028 {
2029 template <typename Range>
2030 using target_view_type = drop_while_view<Range, Pred>;
2031
2032 constexpr drop_while_range_adapter_closure(Pred& pred)
2033 : _pred{pred}
2034 {
2035 }
2036
2037 template <typename Range>
2038 constexpr auto operator()(Range&& r) const
2039 {
2040 return drop_while_view(views::all(etl::forward<Range>(r)), _pred);
2041 }
2042
2043 Pred _pred;
2044 };
2045
2046 namespace views
2047 {
2048 namespace private_views
2049 {
2050 struct drop_while
2051 {
2052 template <class Range, class Pred>
2053 constexpr auto operator()(Range&& r, Pred pred) const
2054 {
2055 return drop_while_view(views::all(etl::forward<Range>(r)), pred);
2056 }
2057
2058 template <class Pred>
2059 constexpr auto operator()(Pred pred) const
2060 {
2061 return ranges::drop_while_range_adapter_closure(pred);
2062 }
2063 };
2064 } // namespace private_views
2065
2066 inline constexpr private_views::drop_while drop_while;
2067 } // namespace views
2068
2069 // Own implementation instead of using etl::min to avoid including
2070 // algorithm.h
2071 namespace private_views
2072 {
2073 template <typename T>
2074 constexpr T min(T a, T b)
2075 {
2076 return a < b ? a : b;
2077 }
2078 } // namespace private_views
2079
2080 template <class Range>
2081 class take_view : public etl::ranges::view_interface<take_view<Range>>
2082 {
2083 public:
2084
2085 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
2086 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
2087 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
2088
2089 constexpr take_view(Range&& r, ranges::range_difference_t<Range> take_n)
2090 : _r{etl::move(r)}
2091 , _take_n{private_views::min<ranges::range_difference_t<Range>>(take_n, etl::distance(ETL_OR_STD::cbegin(r), ETL_OR_STD::cend(r)))}
2092 {
2093 }
2094
2095 take_view(const take_view& other) = default;
2096
2097 constexpr Range base() const&
2098 {
2099 return _r;
2100 }
2101
2102 constexpr iterator begin() const
2103 {
2104 return iterator(ETL_OR_STD::begin(_r));
2105 }
2106
2107 constexpr iterator end() const
2108 {
2109 iterator result{begin()};
2110 etl::advance(result, _take_n);
2111 return result;
2112 }
2113
2114 constexpr ranges::range_difference_t<Range> size() const
2115 {
2116 return _take_n;
2117 }
2118
2119 private:
2120
2121 Range _r;
2122 ranges::range_difference_t<Range> _take_n;
2123 };
2124
2125 template <class Range>
2126 take_view(Range&&, ranges::range_difference_t<Range>) -> take_view<views::all_t<Range>>;
2127
2128 struct take_range_adapter_closure : public range_adapter_closure<take_range_adapter_closure>
2129 {
2130 template <typename Range>
2131 using target_view_type = take_view<Range>;
2132
2133 template <class DifferenceType>
2134 constexpr take_range_adapter_closure(DifferenceType take_n)
2135 : _take_n{static_cast<size_t>(take_n)}
2136 {
2137 }
2138
2139 template <typename Range>
2140 constexpr auto operator()(Range&& r) const
2141 {
2142 return take_view(views::all(etl::forward<Range>(r)), static_cast<ranges::range_difference_t<Range>>(_take_n));
2143 }
2144
2145 const size_t _take_n;
2146 };
2147
2148 namespace views
2149 {
2150 namespace private_views
2151 {
2152 struct take
2153 {
2154 template <class Range>
2155 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> take_n) const
2156 {
2157 return take_view(views::all(etl::forward<Range>(r)), take_n);
2158 }
2159
2160 template <class DifferenceType>
2161 constexpr auto operator()(DifferenceType take_n) const
2162 {
2163 return ranges::take_range_adapter_closure(take_n);
2164 }
2165 };
2166 } // namespace private_views
2167
2168 inline constexpr private_views::take take;
2169 } // namespace views
2170
2171 template <class Range, class Pred>
2172 class take_while_view : public etl::ranges::view_interface<take_while_view<Range, Pred>>
2173 {
2174 public:
2175
2176 using iterator = typename etl::ranges::private_ranges::iterator_trait<Range>::iterator;
2177 using const_iterator = typename etl::ranges::private_ranges::iterator_trait< Range>::const_iterator;
2178 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
2179
2180 constexpr take_while_view(Range&& r, Pred pred)
2181 : _r{etl::move(r)}
2182 , _pred{etl::move(pred)}
2183 , _end_cache{}
2184 , _end_cache_valid{false}
2185 {
2186 }
2187
2188 constexpr const Range base() const&
2189 {
2190 return _r;
2191 }
2192
2193 constexpr const Pred& pred() const
2194 {
2195 return _pred;
2196 }
2197
2198 constexpr auto begin() const
2199 {
2200 return ETL_OR_STD::begin(_r);
2201 }
2202
2203 constexpr auto end() const
2204 {
2205 if (!_end_cache_valid)
2206 {
2207 iterator result{ETL_OR_STD::begin(_r)};
2208 while (result != ETL_OR_STD::end(_r) && _pred(*result))
2209 {
2210 ++result;
2211 }
2212 _end_cache = result;
2213 _end_cache_valid = true;
2214 }
2215 return _end_cache;
2216 }
2217
2218 private:
2219
2220 Range _r;
2221 Pred _pred;
2222 mutable iterator _end_cache;
2223 mutable bool _end_cache_valid;
2224 };
2225
2226 template <class Range, class Pred>
2227 take_while_view(Range&&, Pred) -> take_while_view<views::all_t<Range>, Pred>;
2228
2229 template <typename Pred>
2230 struct take_while_range_adapter_closure : public range_adapter_closure<take_while_range_adapter_closure<Pred>>
2231 {
2232 template <typename Range>
2233 using target_view_type = take_while_view<Range, Pred>;
2234
2235 constexpr take_while_range_adapter_closure(Pred pred)
2236 : _pred{etl::move(pred)}
2237 {
2238 }
2239
2240 template <typename Range>
2241 constexpr auto operator()(Range&& r) const
2242 {
2243 return take_while_view(views::all(etl::forward<Range>(r)), _pred);
2244 }
2245
2246 Pred _pred;
2247 };
2248
2249 namespace views
2250 {
2251 namespace private_views
2252 {
2253 struct take_while
2254 {
2255 template <class Range, class Pred>
2256 constexpr auto operator()(Range&& r, Pred&& pred) const
2257 {
2258 return take_while_view(views::all(etl::forward<Range>(r)), etl::forward<Pred>(pred));
2259 }
2260
2261 template <class Pred>
2262 constexpr auto operator()(Pred&& pred) const
2263 {
2264 return ranges::take_while_range_adapter_closure(etl::forward<Pred>(pred));
2265 }
2266 };
2267 } // namespace private_views
2268
2269 inline constexpr private_views::take_while take_while;
2270 } // namespace views
2271
2272 template <class Range>
2273 class join_iterator
2274 {
2275 public:
2276
2277 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2278
2279 using iterator = typename trait::iterator;
2280 using const_iterator = typename trait::const_iterator;
2281 using difference_type = typename trait::difference_type;
2282
2283 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2284
2285 using InnerRange = decltype(*(ETL_OR_STD::begin(etl::declval<Range>())));
2286 using inner_trait = typename etl::ranges::private_ranges::iterator_trait<InnerRange>;
2287 using inner_iterator = typename inner_trait::iterator;
2288
2289 // Derive the reference type from the inner iterator's actual dereference, so that
2290 // inner ranges whose iterators yield prvalues (e.g. repeat_view) are supported,
2291 // matching std::ranges::join_view (reference = range_reference_t<InnerRange>).
2292 using reference = decltype(*etl::declval<const inner_iterator&>());
2293 using value_type = etl::remove_cvref_t<reference>;
2294 using pointer = typename inner_trait::pointer;
2295
2296 join_iterator(iterator it, iterator it_end)
2297 : _it(it)
2298 , _it_end(it_end)
2299 , _inner_it(it != it_end ? ETL_OR_STD::begin(*it) : inner_iterator{})
2300 , _inner_it_end(it != it_end ? ETL_OR_STD::end(*it) : inner_iterator{})
2301 {
2302 adjust_iterator();
2303 }
2304
2305 join_iterator(const join_iterator& other) = default;
2306
2307 join_iterator& operator++()
2308 {
2309 if (_inner_it != _inner_it_end)
2310 {
2311 ++_inner_it;
2312 }
2313
2314 adjust_iterator();
2315
2316 return *this;
2317 }
2318
2319 join_iterator operator++(int)
2320 {
2321 join_iterator tmp{*this};
2322
2323 if (_inner_it != _inner_it_end)
2324 {
2325 _inner_it++;
2326 }
2327
2328 adjust_iterator();
2329
2330 return tmp;
2331 }
2332
2333 join_iterator& operator=(const join_iterator& other)
2334 {
2335 _it = other._it;
2336 _it_end = other._it_end;
2337 _inner_it = other._inner_it;
2338 _inner_it_end = other._inner_it_end;
2339
2340 adjust_iterator();
2341
2342 return *this;
2343 }
2344
2345 reference operator*() const
2346 {
2347 return *_inner_it;
2348 }
2349
2350 constexpr bool operator==(const join_iterator& other) const
2351 {
2352 return (_it == other._it && _inner_it == other._inner_it) || (_it == _it_end && other._it == other._it_end);
2353 }
2354
2355 constexpr bool operator!=(const join_iterator& other) const
2356 {
2357 return !(*this == other);
2358 }
2359
2360 private:
2361
2362 void adjust_iterator()
2363 {
2364 while (_it != _it_end && _inner_it == _inner_it_end)
2365 {
2366 ++_it;
2367 if (_it != _it_end)
2368 {
2369 _inner_it = ETL_OR_STD::begin((*_it));
2370 _inner_it_end = ETL_OR_STD::end((*_it));
2371 }
2372 }
2373 }
2374
2375 iterator _it;
2376 iterator _it_end;
2377 inner_iterator _inner_it;
2378 inner_iterator _inner_it_end;
2379 };
2380
2381 template <class Range>
2382 class join_view : public etl::ranges::view_interface<join_view<Range>>
2383 {
2384 public:
2385
2386 using iterator = join_iterator<Range>;
2387 using const_iterator = join_iterator<Range>;
2388
2389 join_view(Range&& r)
2390 : _r{etl::move(r)}
2391 {
2392 }
2393
2394 constexpr Range base() const&
2395 {
2396 return _r;
2397 }
2398
2399 constexpr iterator begin() const
2400 {
2401 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r));
2402 }
2403
2404 constexpr iterator end() const
2405 {
2406 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r));
2407 }
2408
2409 private:
2410
2411 Range _r;
2412 };
2413
2414 struct join_range_adapter_closure : public range_adapter_closure<join_range_adapter_closure>
2415 {
2416 template <typename Range>
2417 using target_view_type = join_view<Range>;
2418
2419 join_range_adapter_closure() = default;
2420
2421 template <typename Range>
2422 constexpr auto operator()(Range&& r)
2423 {
2424 return join_view(views::all(etl::forward<Range>(r)));
2425 }
2426 };
2427
2428 template <class Range>
2429 explicit join_view(Range&&) -> join_view<views::all_t<Range>>;
2430
2431 namespace views
2432 {
2433 namespace private_views
2434 {
2435 struct join : public range_adapter_closure_base
2436 {
2437 template <class Range>
2438 constexpr auto operator()(Range&& r) const
2439 {
2440 return join_view(views::all(etl::forward<Range>(r)));
2441 }
2442
2443 constexpr auto operator()() const
2444 {
2445 return ranges::join_range_adapter_closure();
2446 }
2447 };
2448 } // namespace private_views
2449
2450 inline constexpr private_views::join join;
2451 } // namespace views
2452
2453 namespace private_ranges
2454 {
2455 //*********************************************************************
2463 //*********************************************************************
2464 template <typename InnerRef, typename PatternRef>
2465 struct join_with_reference
2466 {
2467 using value_type = etl::common_type_t<etl::remove_cvref_t<InnerRef>, etl::remove_cvref_t<PatternRef>>;
2468
2469 static constexpr bool same_underlying = etl::is_same<etl::remove_cvref_t<InnerRef>, etl::remove_cvref_t<PatternRef>>::value;
2470 static constexpr bool both_lvalue = etl::is_lvalue_reference<InnerRef>::value && etl::is_lvalue_reference<PatternRef>::value;
2471 static constexpr bool any_const =
2472 etl::is_const<etl::remove_reference_t<InnerRef>>::value || etl::is_const<etl::remove_reference_t<PatternRef>>::value;
2473
2474 using type = etl::conditional_t<same_underlying && both_lvalue, etl::conditional_t<any_const, const value_type&, value_type&>, value_type>;
2475 };
2476 } // namespace private_ranges
2477
2478 template <class Range, class Pattern>
2479 class join_with_iterator
2480 {
2481 public:
2482
2483 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2484
2485 using iterator = typename trait::iterator;
2486 using const_iterator = typename trait::const_iterator;
2487 using difference_type = typename trait::difference_type;
2488
2489 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2490
2491 using InnerRange = decltype(*(ETL_OR_STD::begin(etl::declval<Range>())));
2492 using inner_trait = typename etl::ranges::private_ranges::iterator_trait<InnerRange>;
2493 using inner_iterator = typename inner_trait::iterator;
2494
2495 // Deduce the pattern iterator from iterating the (const) pattern view directly,
2496 // so reference-backed patterns (e.g. ref_view) stay mutable while value-backed
2497 // patterns (e.g. single_view) are read as const.
2498 using pattern_iterator = decltype(ETL_OR_STD::begin(etl::declval<const Pattern&>()));
2499
2500 // Element type follows [range.join.with.iterator]: the common type / common
2501 // reference of the inner range's and the pattern's elements. This keeps the
2502 // declared reference consistent with operator* and supports inner ranges whose
2503 // iterators yield prvalues (e.g. repeat_view).
2504 using inner_reference = decltype(*etl::declval<const inner_iterator&>());
2505 using pattern_reference = decltype(*etl::declval<const pattern_iterator&>());
2506
2507 using value_type = etl::common_type_t<etl::remove_cvref_t<inner_reference>, etl::remove_cvref_t<pattern_reference>>;
2508 using reference = typename etl::ranges::private_ranges::join_with_reference<inner_reference, pattern_reference>::type;
2509 using pointer = typename inner_trait::pointer;
2510
2511 join_with_iterator(iterator it, iterator it_end, const Pattern& pattern)
2512 : _it(it)
2513 , _it_end(it_end)
2514 , _inner_it(it != it_end ? ETL_OR_STD::begin(*it) : inner_iterator{})
2515 , _inner_it_end(it != it_end ? ETL_OR_STD::end(*it) : inner_iterator{})
2516 , _pattern(pattern)
2517 , _pattern_it(ETL_OR_STD::end(pattern))
2518 , _pattern_it_end(ETL_OR_STD::end(pattern))
2519 {
2520 adjust_iterator();
2521 }
2522
2523 join_with_iterator(const join_with_iterator& other) = default;
2524
2525 join_with_iterator& operator++()
2526 {
2527 if (_pattern_it != _pattern_it_end)
2528 {
2529 ++_pattern_it;
2530 }
2531 else if (_inner_it != _inner_it_end)
2532 {
2533 ++_inner_it;
2534 }
2535
2536 adjust_iterator();
2537
2538 return *this;
2539 }
2540
2541 join_with_iterator operator++(int)
2542 {
2543 join_with_iterator tmp{*this};
2544
2545 if (_pattern_it != _pattern_it_end)
2546 {
2547 _pattern_it++;
2548 }
2549 else if (_inner_it != _inner_it_end)
2550 {
2551 _inner_it++;
2552 }
2553
2554 adjust_iterator();
2555
2556 return tmp;
2557 }
2558
2559 join_with_iterator& operator=(const join_with_iterator& other)
2560 {
2561 _it = other._it;
2562 _it_end = other._it_end;
2563 _inner_it = other._inner_it;
2564 _inner_it_end = other._inner_it_end;
2565 _pattern_it = other._pattern_it;
2566 _pattern_it_end = other._pattern_it_end;
2567
2568 adjust_iterator();
2569
2570 return *this;
2571 }
2572
2573 reference operator*() const
2574 {
2575 if (_pattern_it != _pattern_it_end)
2576 {
2577 return *_pattern_it;
2578 }
2579 return *_inner_it;
2580 }
2581
2582 constexpr bool operator==(const join_with_iterator& other) const
2583 {
2584 return (_it == other._it && _inner_it == other._inner_it && _pattern_it == other._pattern_it) || (_it == _it_end);
2585 }
2586
2587 constexpr bool operator!=(const join_with_iterator& other) const
2588 {
2589 return !(*this == other);
2590 }
2591
2592 private:
2593
2594 void adjust_iterator()
2595 {
2596 if (_it != _it_end && _inner_it == _inner_it_end && _pattern_it == _pattern_it_end)
2597 {
2598 ++_it;
2599 if (_it != _it_end)
2600 {
2601 _pattern_it = ETL_OR_STD::begin(_pattern);
2602 _pattern_it_end = ETL_OR_STD::end(_pattern);
2603 _inner_it = ETL_OR_STD::begin(*_it);
2604 _inner_it_end = ETL_OR_STD::end(*_it);
2605 }
2606 }
2607 }
2608
2609 iterator _it;
2610 iterator _it_end;
2611 inner_iterator _inner_it;
2612 inner_iterator _inner_it_end;
2613 const Pattern& _pattern;
2614 pattern_iterator _pattern_it;
2615 pattern_iterator _pattern_it_end;
2616 };
2617
2618 template <class Range, class Pattern>
2619 class join_with_view : public etl::ranges::view_interface<join_with_view<Range, Pattern>>
2620 {
2621 public:
2622
2623 using iterator = join_with_iterator<Range, Pattern>;
2624 using const_iterator = join_with_iterator<Range, Pattern>;
2625
2626 join_with_view(Range&& r, Pattern&& pattern)
2627 : _r{etl::move(r)}
2628 , _pattern{etl::move(pattern)}
2629 {
2630 }
2631
2632 constexpr Range base() const&
2633 {
2634 return _r;
2635 }
2636
2637 constexpr iterator begin() const
2638 {
2639 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pattern);
2640 }
2641
2642 constexpr iterator end() const
2643 {
2644 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pattern);
2645 }
2646
2647 private:
2648
2649 Range _r;
2650 Pattern _pattern;
2651 };
2652
2653 // For range as separator
2654 template <class Range, class Pattern>
2655 join_with_view(Range&&, Pattern&&) -> join_with_view<views::all_t<Range>, views::all_t<Pattern>>;
2656
2657 // For single value as separator
2658 template <class Range>
2659 join_with_view(Range&&, etl::ranges::range_value_t<etl::ranges::range_reference_t<Range>>)
2660 -> join_with_view<views::all_t<Range>, etl::ranges::single_view<etl::ranges::range_value_t< etl::ranges::range_reference_t<Range>>>>;
2661
2662 namespace private_ranges
2663 {
2664 template <class Pattern>
2665 constexpr auto make_pattern(Pattern&& pattern)
2666 {
2667 if constexpr (etl::is_base_of_v<etl::ranges::view_interface<Pattern>, Pattern>)
2668 {
2669 return etl::forward<Pattern>(pattern);
2670 }
2671 else
2672 {
2673 return etl::ranges::single_view<Pattern>(etl::forward<Pattern>(pattern));
2674 }
2675 }
2676
2677 template <class Pattern>
2678 constexpr auto make_pattern(const Pattern& pattern)
2679 {
2680 if constexpr (etl::is_array_v<etl::remove_reference_t<Pattern>> || etl::is_range_v<etl::remove_reference_t<Pattern>>)
2681 {
2682 return views::all(pattern);
2683 }
2684 else
2685 {
2686 return etl::ranges::single_view<etl::remove_reference_t<Pattern>>(pattern);
2687 }
2688 }
2689 } // namespace private_ranges
2690
2691 template <class Pattern>
2692 struct join_with_range_adapter_closure : public range_adapter_closure<join_with_range_adapter_closure<Pattern>>
2693 {
2694 template <typename Range>
2695 using target_view_type = join_with_view<Range, Pattern>;
2696
2697 join_with_range_adapter_closure(const Pattern& pattern)
2698 : _pattern(pattern)
2699 {
2700 }
2701
2702 template <typename Range>
2703 constexpr auto operator()(Range&& r)
2704 {
2705 return join_with_view(views::all(etl::forward<Range>(r)), private_ranges::make_pattern<Pattern>(_pattern));
2706 }
2707
2708 const Pattern& _pattern;
2709 };
2710
2711 namespace views
2712 {
2713 namespace private_views
2714 {
2715 struct join_with
2716 {
2717 template <class Range, class Pattern>
2718 constexpr auto operator()(Range&& r, Pattern&& pattern) const
2719 {
2720 return join_with_view(views::all(etl::forward<Range>(r)),
2721 views::all(etl::ranges::private_ranges::make_pattern<Pattern>(etl::forward<Pattern>(pattern))));
2722 }
2723
2724 template <class Pattern>
2725 constexpr auto operator()(const Pattern& pattern) const
2726 {
2727 return ranges::join_with_range_adapter_closure(pattern);
2728 }
2729 };
2730 } // namespace private_views
2731
2732 inline constexpr private_views::join_with join_with;
2733 } // namespace views
2734
2735 template <class Range, class Pattern>
2736 class split_iterator
2737 {
2738 public:
2739
2740 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
2741
2742 using iterator = typename trait::iterator;
2743 using const_iterator = typename trait::const_iterator;
2744 using difference_type = typename trait::difference_type;
2745
2746 using iterator_category = ETL_OR_STD::forward_iterator_tag;
2747
2748 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
2749 using pattern_const_iterator = typename pattern_trait::const_iterator;
2750
2751 using value_type = etl::ranges::subrange<iterator>;
2752 using pointer = value_type*;
2753 using reference = value_type;
2754
2755 split_iterator(iterator it, iterator it_end, const Pattern& pattern, bool is_end = false)
2756 : _it(it)
2757 , _it_end(it_end)
2758 , _pattern(pattern)
2759 , _next(find_next())
2760 , _trailing_empty(!is_end && _it == _it_end)
2761 {
2762 }
2763
2764 split_iterator(const split_iterator& other) = default;
2765
2766 split_iterator& operator++()
2767 {
2768 _it = _next;
2769
2770 if (_it != _it_end)
2771 {
2772 // Skip past the delimiter
2773 auto pat_size = etl::distance(ETL_OR_STD::cbegin(_pattern), ETL_OR_STD::cend(_pattern));
2774 for (difference_type i = 0; i < pat_size && _it != _it_end; ++i)
2775 {
2776 ++_it;
2777 }
2778 _next = find_next();
2779 // If we landed exactly at _it_end after skipping the delimiter,
2780 // there is one more trailing empty segment to emit.
2781 if (_it == _it_end && !_trailing_empty)
2782 {
2783 _trailing_empty = true;
2784 }
2785 }
2786 else
2787 {
2788 // We were at _it_end; this was the trailing empty segment.
2789 _trailing_empty = false;
2790 }
2791
2792 return *this;
2793 }
2794
2795 split_iterator operator++(int)
2796 {
2797 split_iterator tmp{*this};
2798 ++(*this);
2799 return tmp;
2800 }
2801
2802 split_iterator& operator=(const split_iterator& other)
2803 {
2804 _it = other._it;
2805 _it_end = other._it_end;
2806 _next = other._next;
2807 _trailing_empty = other._trailing_empty;
2808 return *this;
2809 }
2810
2811 value_type operator*() const
2812 {
2813 return value_type(_it, _next);
2814 }
2815
2816 constexpr bool operator==(const split_iterator& other) const
2817 {
2818 if (_it == _it_end && other._it == other._it_end)
2819 {
2820 return _trailing_empty == other._trailing_empty;
2821 }
2822 return _it == other._it;
2823 }
2824
2825 constexpr bool operator!=(const split_iterator& other) const
2826 {
2827 return !(*this == other);
2828 }
2829
2830 private:
2831
2832 iterator find_next() const
2833 {
2834 auto pat_begin = ETL_OR_STD::cbegin(_pattern);
2835 auto pat_end = ETL_OR_STD::cend(_pattern);
2836 auto pat_size = etl::distance(pat_begin, pat_end);
2837
2838 if (pat_size == 0)
2839 {
2840 // Empty pattern: split between each element
2841 auto result = _it;
2842 if (result != _it_end)
2843 {
2844 ++result;
2845 }
2846 return result;
2847 }
2848
2849 for (auto search = _it; search != _it_end; ++search)
2850 {
2851 // Try to match the full pattern starting at 'search'
2852 auto s = search;
2853 auto p = pat_begin;
2854 bool match = true;
2855 while (p != pat_end)
2856 {
2857 if (s == _it_end || !(*s == *p))
2858 {
2859 match = false;
2860 break;
2861 }
2862 ++s;
2863 ++p;
2864 }
2865 if (match)
2866 {
2867 return search;
2868 }
2869 }
2870
2871 return _it_end;
2872 }
2873
2874 iterator _it;
2875 iterator _it_end;
2876 const Pattern& _pattern;
2877 iterator _next;
2878 // there is still one empty segment to emit after the last delimiter if
2879 // the last delimiter is at the end of the range
2880 bool _trailing_empty;
2881 };
2882
2883 template <class Range, class Pattern>
2884 class split_view : public etl::ranges::view_interface<split_view<Range, Pattern>>
2885 {
2886 public:
2887
2888 using iterator = split_iterator<Range, Pattern>;
2889 using const_iterator = split_iterator<Range, Pattern>;
2890
2891 split_view(Range&& r, Pattern&& pattern)
2892 : _r{etl::move(r)}
2893 , _pattern{etl::move(pattern)}
2894 {
2895 }
2896
2897 constexpr Range& base() const&
2898 {
2899 return _r;
2900 }
2901
2902 constexpr const Pattern& pattern() const
2903 {
2904 return _pattern;
2905 }
2906
2907 constexpr iterator begin() const
2908 {
2909 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pattern);
2910 }
2911
2912 constexpr iterator end() const
2913 {
2914 auto it = iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pattern, true);
2915 return it;
2916 }
2917
2918 private:
2919
2920 Range _r;
2921 Pattern _pattern;
2922 };
2923
2924 // For range as delimiter (Pattern is a range, not a single value)
2925 template <class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2926 split_view(Range&&, Pattern&&) -> split_view<views::all_t<Range>, views::all_t<Pattern>>;
2927
2928 // For single value as delimiter (Pattern is not a range)
2929 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2930 split_view(Range&&, Pattern&&) -> split_view<views::all_t<Range>, etl::ranges::single_view<etl::decay_t<Pattern>>>;
2931
2932 template <class Pattern>
2933 struct split_range_adapter_closure : public range_adapter_closure<split_range_adapter_closure<Pattern>>
2934 {
2935 template <typename Range>
2936 using target_view_type = split_view<Range, Pattern>;
2937
2938 split_range_adapter_closure(const Pattern& pattern)
2939 : _pattern(pattern)
2940 {
2941 }
2942
2943 template <typename Range>
2944 constexpr auto operator()(Range&& r)
2945 {
2946 // If Pattern is a range, use views::all. If not, wrap in single_view.
2947 if constexpr (etl::is_class_v<etl::decay_t<Pattern>>)
2948 {
2949 return split_view(views::all(etl::forward<Range>(r)), views::all(_pattern));
2950 }
2951 else
2952 {
2953 return split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(_pattern));
2954 }
2955 }
2956
2957 const Pattern& _pattern;
2958 };
2959
2960 namespace views
2961 {
2962 namespace private_views
2963 {
2964 struct split
2965 {
2966 // Range + Pattern (Pattern is a range)
2967 template < class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2968 constexpr auto operator()(Range&& r, Pattern&& pattern) const
2969 {
2970 return split_view(views::all(etl::forward<Range>(r)), views::all(etl::forward<Pattern>(pattern)));
2971 }
2972
2973 // Range + Pattern (Pattern is a single value)
2974 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
2975 constexpr auto operator()(Range&& r, Pattern&& pattern) const
2976 {
2977 return split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(pattern));
2978 }
2979
2980 // Pipe closure
2981 template <class Pattern>
2982 constexpr auto operator()(const Pattern& pattern) const
2983 {
2984 return ranges::split_range_adapter_closure<Pattern>(pattern);
2985 }
2986 };
2987 } // namespace private_views
2988
2989 inline constexpr private_views::split split;
2990 } // namespace views
2991
2992 //*************************************************************************
2998 //*************************************************************************
2999
3000 template <class Range, class Pattern>
3001 class lazy_split_view;
3002
3006 template <class Range, class Pattern>
3007 class lazy_split_inner_range
3008 {
3009 public:
3010
3011 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
3012 using iterator_type = typename trait::iterator;
3013 using const_iterator_type = typename trait::const_iterator;
3014 using value_type = typename trait::value_type;
3015
3016 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
3017 using pattern_const_iterator = typename pattern_trait::const_iterator;
3018
3019 class iterator
3020 {
3021 public:
3022
3023 using value_type = typename trait::value_type;
3024 using difference_type = typename trait::difference_type;
3025 using reference = decltype(*etl::declval<iterator_type&>());
3026 using pointer = etl::remove_reference_t<reference>*;
3027 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3028
3029 iterator() = default;
3030
3031 iterator(iterator_type current, iterator_type segment_end, bool is_end)
3032 : _current_it(current)
3033 , _segment_end(segment_end)
3034 , _is_end(is_end || (current == segment_end))
3035 {
3036 }
3037
3038 constexpr decltype(auto) operator*() const
3039 {
3040 return *_current_it;
3041 }
3042
3043 pointer operator->() const
3044 {
3045 return &(*_current_it);
3046 }
3047
3048 iterator& operator++()
3049 {
3050 ++_current_it;
3051 if (_current_it == _segment_end)
3052 {
3053 _is_end = true;
3054 }
3055 return *this;
3056 }
3057
3058 iterator operator++(int)
3059 {
3060 iterator tmp{*this};
3061 ++(*this);
3062 return tmp;
3063 }
3064
3065 constexpr bool operator==(const iterator& other) const
3066 {
3067 if (_is_end && other._is_end)
3068 {
3069 return true;
3070 }
3071 if (_is_end != other._is_end)
3072 {
3073 return false;
3074 }
3075 return _current_it == other._current_it;
3076 }
3077
3078 constexpr bool operator!=(const iterator& other) const
3079 {
3080 return !(*this == other);
3081 }
3082
3083 private:
3084
3085 iterator_type _current_it{};
3086 iterator_type _segment_end{};
3087 bool _is_end = true;
3088 };
3089
3090 using const_iterator = iterator;
3091
3092 lazy_split_inner_range(iterator_type segment_begin, iterator_type segment_end)
3093 : _segment_begin(segment_begin)
3094 , _segment_end(segment_end)
3095 {
3096 }
3097
3098 iterator begin() const
3099 {
3100 return iterator(_segment_begin, _segment_end, false);
3101 }
3102
3103 iterator end() const
3104 {
3105 return iterator(_segment_end, _segment_end, true);
3106 }
3107
3108 bool empty() const
3109 {
3110 return _segment_begin == _segment_end;
3111 }
3112
3113 private:
3114
3115 iterator_type _segment_begin;
3116 iterator_type _segment_end;
3117 };
3118
3122 template <class Range, class Pattern>
3123 class lazy_split_iterator
3124 {
3125 public:
3126
3127 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
3128
3129 using source_iterator = typename trait::iterator;
3130 using const_iterator = typename trait::const_iterator;
3131 using difference_type = typename trait::difference_type;
3132
3133 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3134
3135 using pattern_trait = typename etl::ranges::private_ranges::iterator_trait<Pattern>;
3136 using pattern_const_iterator = typename pattern_trait::const_iterator;
3137
3138 using value_type = lazy_split_inner_range<Range, Pattern>;
3139 using pointer = value_type*;
3140 using reference = value_type;
3141
3142 lazy_split_iterator(source_iterator it, source_iterator it_end, const Pattern& pattern, bool is_end = false)
3143 : _it(it)
3144 , _it_end(it_end)
3145 , _pattern(pattern)
3146 , _next(find_next())
3147 , _trailing_empty(!is_end && _it == _it_end)
3148 {
3149 }
3150
3151 lazy_split_iterator(const lazy_split_iterator& other) = default;
3152
3153 lazy_split_iterator& operator=(const lazy_split_iterator& other)
3154 {
3155 _it = other._it;
3156 _it_end = other._it_end;
3157 _next = other._next;
3158 _trailing_empty = other._trailing_empty;
3159 return *this;
3160 }
3161
3162 lazy_split_iterator& operator++()
3163 {
3164 _it = _next;
3165
3166 if (_it != _it_end)
3167 {
3168 // Skip past the matched delimiter
3169 auto pat_size = etl::distance(ETL_OR_STD::cbegin(_pattern), ETL_OR_STD::cend(_pattern));
3170 for (difference_type i = 0; i < pat_size && _it != _it_end; ++i)
3171 {
3172 ++_it;
3173 }
3174 _next = find_next();
3175 // If we landed exactly at _it_end after skipping the delimiter,
3176 // there is one more trailing empty segment to emit.
3177 if (_it == _it_end && !_trailing_empty)
3178 {
3179 _trailing_empty = true;
3180 }
3181 }
3182 else
3183 {
3184 // We were at _it_end; this was the trailing empty segment.
3185 _trailing_empty = false;
3186 }
3187
3188 return *this;
3189 }
3190
3191 lazy_split_iterator operator++(int)
3192 {
3193 lazy_split_iterator tmp{*this};
3194 ++(*this);
3195 return tmp;
3196 }
3197
3200 value_type operator*() const
3201 {
3202 return value_type(_it, _next);
3203 }
3204
3205 constexpr bool operator==(const lazy_split_iterator& other) const
3206 {
3207 if (_it == _it_end && other._it == other._it_end)
3208 {
3209 return _trailing_empty == other._trailing_empty;
3210 }
3211 return _it == other._it;
3212 }
3213
3214 constexpr bool operator!=(const lazy_split_iterator& other) const
3215 {
3216 return !(*this == other);
3217 }
3218
3219 private:
3220
3223 source_iterator find_next() const
3224 {
3225 auto pat_begin = ETL_OR_STD::cbegin(_pattern);
3226 auto pat_end = ETL_OR_STD::cend(_pattern);
3227 auto pat_size = etl::distance(pat_begin, pat_end);
3228
3229 if (pat_size == 0)
3230 {
3231 // Empty pattern: split between each element
3232 auto result = _it;
3233 if (result != _it_end)
3234 {
3235 ++result;
3236 }
3237 return result;
3238 }
3239
3240 for (auto search = _it; search != _it_end; ++search)
3241 {
3242 // Try to match the full pattern starting at 'search'
3243 auto s = search;
3244 auto p = pat_begin;
3245 bool match = true;
3246 while (p != pat_end)
3247 {
3248 if (s == _it_end || !(*s == *p))
3249 {
3250 match = false;
3251 break;
3252 }
3253 ++s;
3254 ++p;
3255 }
3256 if (match)
3257 {
3258 return search;
3259 }
3260 }
3261
3262 return _it_end;
3263 }
3264
3265 source_iterator _it;
3266 source_iterator _it_end;
3267 const Pattern& _pattern;
3268 source_iterator _next;
3269 bool _trailing_empty;
3270 };
3271
3272 template <class Range, class Pattern>
3273 class lazy_split_view : public etl::ranges::view_interface<lazy_split_view<Range, Pattern>>
3274 {
3275 public:
3276
3277 using iterator = lazy_split_iterator<Range, Pattern>;
3278 using const_iterator = lazy_split_iterator<Range, Pattern>;
3279
3280 lazy_split_view(Range&& r, Pattern&& pattern)
3281 : _r{etl::move(r)}
3282 , _pattern{etl::move(pattern)}
3283 {
3284 }
3285
3286 constexpr Range& base() const&
3287 {
3288 return _r;
3289 }
3290
3291 constexpr const Pattern& pattern() const
3292 {
3293 return _pattern;
3294 }
3295
3296 constexpr iterator begin() const
3297 {
3298 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pattern);
3299 }
3300
3301 constexpr iterator end() const
3302 {
3303 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pattern, true);
3304 }
3305
3306 private:
3307
3308 Range _r;
3309 Pattern _pattern;
3310 };
3311
3312 // Deduction guide: range delimiter (Pattern is a range)
3313 template <class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3314 lazy_split_view(Range&&, Pattern&&) -> lazy_split_view<views::all_t<Range>, views::all_t<Pattern>>;
3315
3316 // Deduction guide: single-value delimiter (Pattern is not a range)
3317 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3318 lazy_split_view(Range&&, Pattern&&) -> lazy_split_view<views::all_t<Range>, etl::ranges::single_view<etl::decay_t<Pattern>>>;
3319
3320 template <class Pattern>
3321 struct lazy_split_range_adapter_closure : public range_adapter_closure<lazy_split_range_adapter_closure<Pattern>>
3322 {
3323 template <typename Range>
3324 using target_view_type = lazy_split_view<Range, Pattern>;
3325
3326 lazy_split_range_adapter_closure(const Pattern& pattern)
3327 : _pattern(pattern)
3328 {
3329 }
3330
3331 template <typename Range>
3332 constexpr auto operator()(Range&& r)
3333 {
3334 if constexpr (etl::is_class_v<etl::decay_t<Pattern>>)
3335 {
3336 return lazy_split_view(views::all(etl::forward<Range>(r)), views::all(_pattern));
3337 }
3338 else
3339 {
3340 return lazy_split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(_pattern));
3341 }
3342 }
3343
3344 const Pattern& _pattern;
3345 };
3346
3347 namespace views
3348 {
3349 namespace private_views
3350 {
3351 struct lazy_split
3352 {
3353 // Range + Pattern (Pattern is a range)
3354 template < class Range, class Pattern, etl::enable_if_t<etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3355 constexpr auto operator()(Range&& r, Pattern&& pattern) const
3356 {
3357 return lazy_split_view(views::all(etl::forward<Range>(r)), views::all(etl::forward<Pattern>(pattern)));
3358 }
3359
3360 // Range + Pattern (Pattern is a single value)
3361 template < class Range, class Pattern, etl::enable_if_t<!etl::is_class_v<etl::decay_t<Pattern>>, int> = 0>
3362 constexpr auto operator()(Range&& r, Pattern&& pattern) const
3363 {
3364 return lazy_split_view(views::all(etl::forward<Range>(r)), etl::ranges::single_view(pattern));
3365 }
3366
3367 // Pipe closure
3368 template <class Pattern>
3369 constexpr auto operator()(const Pattern& pattern) const
3370 {
3371 return ranges::lazy_split_range_adapter_closure<Pattern>(pattern);
3372 }
3373 };
3374 } // namespace private_views
3375
3376 inline constexpr private_views::lazy_split lazy_split;
3377 } // namespace views
3378
3379 namespace views
3380 {
3381 namespace private_views
3382 {
3383 struct counted
3384 {
3385 template <class Iterator, class DifferenceType>
3386 constexpr auto operator()(Iterator&& it, DifferenceType&& count) const
3387 {
3388 using T = etl::decay_t<decltype(it)>;
3389 using D = etl::iter_difference_t<T>;
3390
3391 // contiguous_iterator_tag not yet available
3392 // if constexpr(etl::is_same_v<typename
3393 // etl::iterator_traits<Iterator>::iterator_category,
3394 // ETL_OR_STD::contiguous_iterator_tag>)
3395 //{
3396 // return etl::span(etl::to_address(it),
3397 // static_cast<size_t>(static_cast<etl::iter_difference_t<T>>(count)));
3398 //}
3399 // else
3400 if constexpr (etl::is_same_v< typename etl::iterator_traits< Iterator>::iterator_category, ETL_OR_STD::random_access_iterator_tag>)
3401 {
3402 return etl::ranges::subrange(it, it + static_cast<D>(count));
3403 }
3404 else
3405 {
3406 return etl::ranges::subrange(etl::counted_iterator(it, count), etl::default_sentinel);
3407 }
3408 }
3409 };
3410 } // namespace private_views
3411
3412 inline constexpr private_views::counted counted;
3413 } // namespace views
3414
3415 template <class... Ranges>
3416 class concat_view;
3417
3418 template <class... Ranges>
3419 class concat_iterator
3420 {
3421 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3422
3423 public:
3424
3425 using types = typename etl::type_list<Ranges...>;
3426 using first_range = typename etl::type_list_type_at_index_t<types, 0>;
3427 using value_type = typename etl::ranges::private_ranges::iterator_trait< first_range>::value_type;
3428 using reference = typename etl::ranges::private_ranges::iterator_trait< first_range>::reference;
3429 using difference_type = ptrdiff_t;
3430
3431 using iterator_variant_type = typename concat_view<Ranges...>::iterator_variant_type;
3432
3433 concat_iterator(size_t index, concat_view<Ranges...>& view, iterator_variant_type current)
3434 : _ranges_index{index}
3435 , _view(view)
3436 , _current_it(current)
3437 {
3438 }
3439
3440 concat_iterator(const concat_iterator& other) = default;
3441
3442 constexpr reference operator*() const
3443 {
3444 return _view.get_value(_ranges_index, _current_it);
3445 }
3446
3447 constexpr decltype(auto) operator[](difference_type pos) const
3448 {
3449 auto tmp = *this;
3450 if (pos > 0)
3451 {
3452 for (difference_type i = 0; i < pos; ++i)
3453 {
3454 tmp._view.advance(tmp._ranges_index, tmp._current_it, 1);
3455 }
3456 }
3457 if (pos < 0)
3458 {
3459 for (difference_type i = 0; i < -pos; ++i)
3460 {
3461 tmp._view.advance(tmp._ranges_index, tmp._current_it, -1);
3462 }
3463 }
3464 return *tmp;
3465 }
3466
3467 constexpr concat_iterator& operator++()
3468 {
3469 _view.advance(_ranges_index, _current_it, 1);
3470 return *this;
3471 }
3472
3473 constexpr concat_iterator operator++(int)
3474 {
3475 auto result = *this;
3476 _view.advance(_ranges_index, _current_it, 1);
3477 return result;
3478 }
3479
3480 constexpr concat_iterator& operator--()
3481 {
3482 _view.advance(_ranges_index, _current_it, -1);
3483 return *this;
3484 }
3485
3486 constexpr concat_iterator operator--(int)
3487 {
3488 auto result = *this;
3489 _view.advance(_ranges_index, _current_it, -1);
3490 return result;
3491 }
3492
3493 constexpr concat_iterator& operator+=(difference_type n)
3494 {
3495 for (difference_type i = 0; i < n; ++i)
3496 {
3497 _view.advance(_ranges_index, _current_it, 1);
3498 }
3499 return *this;
3500 }
3501
3502 constexpr concat_iterator& operator-=(difference_type n)
3503 {
3504 for (difference_type i = 0; i < n; ++i)
3505 {
3506 _view.advance(_ranges_index, _current_it, -1);
3507 }
3508 return *this;
3509 }
3510
3511 friend constexpr bool operator==(const concat_iterator<Ranges...>& x, etl::default_sentinel_t)
3512 {
3513 return x._ranges_index == x._view.number_of_ranges - 1
3514 && etl::get<x._view.number_of_ranges - 1>(x._current_it) == etl::get<x._view.number_of_ranges - 1>(x._view).end();
3515 }
3516
3517 friend constexpr bool operator==(const concat_iterator<Ranges...>& x, const concat_iterator<Ranges...>& y)
3518 {
3519 return x._ranges_index == y._ranges_index && x._current_it.index() == y._current_it.index() && x._current_it == y._current_it;
3520 }
3521
3522 friend constexpr bool operator!=(const concat_iterator<Ranges...>& x, etl::default_sentinel_t)
3523 {
3524 return !(x == etl::default_sentinel);
3525 }
3526
3527 friend constexpr bool operator!=(const concat_iterator<Ranges...>& x, const concat_iterator<Ranges...>& y)
3528 {
3529 return !(x == y);
3530 }
3531
3532 private:
3533
3534 size_t _ranges_index;
3535 const concat_view<Ranges...>& _view;
3536 iterator_variant_type _current_it;
3537 };
3538
3539 template <class... Ranges>
3540 class concat_view : public etl::ranges::view_interface<concat_view<Ranges...>>
3541 {
3542 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3543
3544 public:
3545
3546 using types = typename etl::type_list<Ranges...>;
3547 using first_range = typename etl::type_list_type_at_index_t<types, 0>;
3548 using value_type = typename etl::ranges::private_ranges::iterator_trait< first_range>::value_type;
3549 using reference = typename etl::ranges::private_ranges::iterator_trait< first_range>::reference;
3550 using iterator = concat_iterator<Ranges...>;
3551 using const_iterator = concat_iterator<Ranges...>;
3552 using difference_type = typename etl::make_signed_t<size_t>;
3553
3554 using iterator_variant_type =
3555 etl::ranges::private_ranges::mini_variant< typename etl::ranges::private_ranges::iterator_trait< Ranges>::iterator...>;
3556
3557 using get_value_delegates_type = reference (*)(const iterator_variant_type& /*current*/);
3558 using advance_delegates_type = void (*)(size_t& /*index*/, const etl::tuple<Ranges...>& /*r*/, iterator_variant_type& /*current*/,
3559 difference_type /*n*/);
3560
3561 static constexpr const size_t number_of_ranges = sizeof...(Ranges);
3562
3563 constexpr concat_view(Ranges&&... r)
3564 : _r{etl::move(r)...}
3565 {
3566 set_delegates();
3567 }
3568
3569 concat_view(const concat_view& other) = default;
3570
3571 constexpr iterator begin()
3572 {
3573 iterator_variant_type current;
3574 current.template emplace<0>(etl::get<0>(_r).begin());
3575 return iterator{0, *this, current};
3576 }
3577
3578 constexpr iterator end()
3579 {
3580 iterator_variant_type current;
3581 current.template emplace<number_of_ranges - 1>(etl::get<number_of_ranges - 1>(_r).end());
3582 return iterator{number_of_ranges - 1, *this, current};
3583 }
3584
3585 constexpr size_t size() const
3586 {
3587 return get_size();
3588 }
3589
3590 private:
3591
3592 template <class... Rs>
3593 friend class concat_iterator;
3594
3595 template <size_t n = 0>
3596 constexpr size_t get_size() const
3597 {
3598 if constexpr (n < etl::tuple_size_v<decltype(_r)>)
3599 {
3600 return etl::get<n>(_r).size() + get_size<n + 1>();
3601 }
3602 else
3603 {
3604 return 0;
3605 }
3606 }
3607
3608 // helper to advance iterator index+iterator variant
3609 void advance(size_t& index, iterator_variant_type& current, difference_type n) const
3610 {
3611 advance_delegates[index](index, _r, current, n);
3612 }
3613
3614 template <size_t i = 0>
3615 void set_delegates()
3616 {
3617 if constexpr (i < number_of_ranges)
3618 {
3619 advance_delegates[i] = [](size_t& index, const etl::tuple<Ranges...>& r, iterator_variant_type& current, difference_type n)
3620 {
3621 if (n > 0)
3622 {
3623 auto end = etl::get<i>(r).end();
3624 auto& it = etl::get<i>(current);
3625 if (it != end)
3626 {
3627 ++it;
3628 }
3629 if (it == end)
3630 {
3631 if constexpr (i + 1 < number_of_ranges)
3632 {
3633 current.template emplace<i + 1>(etl::get<i + 1>(r).begin());
3634 index = i + 1;
3635 }
3636 else
3637 {
3638 // at end of last range
3639 ETL_ASSERT(it == end && i + 1 == number_of_ranges, ETL_ERROR_GENERIC("Wrong iterator state at end"));
3640 }
3641 }
3642 }
3643 if (n < 0)
3644 {
3645 auto begin = etl::get<i>(r).begin();
3646 auto& it = etl::get<i>(current);
3647 if (it == begin)
3648 {
3649 if constexpr (i > 0)
3650 {
3651 current.template emplace<i - 1>(etl::get<i - 1>(r).end());
3652 index = i - 1;
3653
3654 auto begin2 = etl::get<i - 1>(r).begin();
3655 auto& it2 = etl::get<i - 1>(current);
3656 if (it2 != begin2)
3657 {
3658 --it2;
3659 }
3660 }
3661 else
3662 {
3663 // at beginning of first range
3664 ETL_ASSERT(it == begin && i == 0, ETL_ERROR_GENERIC("Wrong iterator state at begin"));
3665 }
3666 }
3667 else
3668 {
3669 it--;
3670 }
3671 }
3672 };
3673
3674 get_value_delegates[i] = [](const iterator_variant_type& current) -> reference
3675 {
3676 return *etl::get<i>(current);
3677 };
3678
3679 set_delegates<i + 1>();
3680 }
3681 }
3682
3683 reference get_value(size_t index, const iterator_variant_type& current) const
3684 {
3685 return get_value_delegates[index](current);
3686 }
3687
3688 etl::tuple<Ranges...> _r;
3689 get_value_delegates_type get_value_delegates[number_of_ranges];
3690 advance_delegates_type advance_delegates[number_of_ranges];
3691 };
3692
3693 template <class... Ranges>
3694 concat_view(Ranges&&...) -> concat_view<views::all_t<Ranges>...>;
3695
3696 namespace views
3697 {
3698 namespace private_views
3699 {
3700 struct concat
3701 {
3702 template <class... Ranges>
3703 constexpr auto operator()(Ranges&&... r) const
3704 {
3705 return concat_view(views::all(etl::forward<Ranges>(r))...);
3706 }
3707 };
3708 } // namespace private_views
3709
3710 inline constexpr private_views::concat concat;
3711 } // namespace views
3712
3713 //*************************************************************************
3717 //*************************************************************************
3718 template <class... Ranges>
3719 class zip_iterator
3720 {
3721 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3722
3723 public:
3724
3725 using iterators_type = etl::tuple< typename etl::ranges::private_ranges::iterator_trait< Ranges>::iterator...>;
3726 using value_type = etl::tuple<typename etl::ranges::private_ranges::iterator_trait< Ranges>::value_type...>;
3727 using difference_type = ptrdiff_t;
3728 // Each tuple element is a reference into the corresponding underlying
3729 // range, so zipped elements remain mutable when the underlying ranges
3730 // are non-const, as required for std::ranges::zip_view.
3731 using reference = etl::tuple<decltype(*etl::declval< typename etl::ranges::private_ranges::iterator_trait<Ranges>::iterator&>())...>;
3732 using pointer = value_type*;
3733
3734 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3735
3736 constexpr zip_iterator(iterators_type iters)
3737 : _iters(iters)
3738 {
3739 }
3740
3741 constexpr zip_iterator(const zip_iterator& other) = default;
3742
3743 constexpr zip_iterator& operator=(const zip_iterator& other) = default;
3744
3745 constexpr zip_iterator& operator++()
3746 {
3747 increment(etl::make_index_sequence<sizeof...(Ranges)>{});
3748 return *this;
3749 }
3750
3751 constexpr zip_iterator operator++(int)
3752 {
3753 zip_iterator tmp = *this;
3754 ++(*this);
3755 return tmp;
3756 }
3757
3758 constexpr reference operator*() const
3759 {
3760 return deref(etl::make_index_sequence<sizeof...(Ranges)>{});
3761 }
3762
3763 friend constexpr bool operator==(const zip_iterator& lhs, const zip_iterator& rhs)
3764 {
3765 return lhs.any_equal(rhs, etl::make_index_sequence<sizeof...(Ranges)>{});
3766 }
3767
3768 friend constexpr bool operator!=(const zip_iterator& lhs, const zip_iterator& rhs)
3769 {
3770 return !(lhs == rhs);
3771 }
3772
3773 private:
3774
3775 template <size_t... Is>
3776 constexpr void increment(etl::index_sequence<Is...>)
3777 {
3778 ((++etl::get<Is>(_iters)), ...);
3779 }
3780
3781 template <size_t... Is>
3782 constexpr reference deref(etl::index_sequence<Is...>) const
3783 {
3784 return reference(*etl::get<Is>(_iters)...);
3785 }
3786
3787 // zip terminates when ANY iterator reaches its end (shortest range
3788 // semantics)
3789 template <size_t... Is>
3790 constexpr bool any_equal(const zip_iterator& other, etl::index_sequence<Is...>) const
3791 {
3792 return ((etl::get<Is>(_iters) == etl::get<Is>(other._iters)) || ...);
3793 }
3794
3795 iterators_type _iters;
3796 };
3797
3798 //*************************************************************************
3803 //*************************************************************************
3804 template <class... Ranges>
3805 class zip_view : public etl::ranges::view_interface<zip_view<Ranges...>>
3806 {
3807 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3808
3809 public:
3810
3811 using iterator = zip_iterator<Ranges...>;
3812 using const_iterator = zip_iterator<Ranges...>;
3813
3814 constexpr zip_view(Ranges&&... r)
3815 : _r{etl::move(r)...}
3816 {
3817 }
3818
3819 zip_view(const zip_view& other) = default;
3820
3821 constexpr const_iterator begin() const
3822 {
3823 return make_begin(etl::make_index_sequence<sizeof...(Ranges)>{});
3824 }
3825
3826 constexpr const_iterator end() const
3827 {
3828 return make_end(etl::make_index_sequence<sizeof...(Ranges)>{});
3829 }
3830
3831 constexpr size_t size() const
3832 {
3833 return get_min_size(etl::make_index_sequence<sizeof...(Ranges)>{});
3834 }
3835
3836 private:
3837
3838 template <size_t... Is>
3839 constexpr const_iterator make_begin(etl::index_sequence<Is...>) const
3840 {
3841 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...));
3842 }
3843
3844 template <size_t... Is>
3845 constexpr const_iterator make_end(etl::index_sequence<Is...>) const
3846 {
3847 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...));
3848 }
3849
3850 template <size_t... Is>
3851 constexpr size_t get_min_size(etl::index_sequence<Is...>) const
3852 {
3853 size_t sizes[] = {static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(etl::get<Is>(_r)), ETL_OR_STD::cend(etl::get<Is>(_r))))...};
3854 size_t min_val = sizes[0];
3855 for (size_t i = 1; i < sizeof...(Ranges); ++i)
3856 {
3857 if (sizes[i] < min_val)
3858 {
3859 min_val = sizes[i];
3860 }
3861 }
3862 return min_val;
3863 }
3864
3865 mutable etl::tuple<Ranges...> _r;
3866 };
3867
3868 template <class... Ranges>
3869 zip_view(Ranges&&...) -> zip_view<views::all_t<Ranges>...>;
3870
3871 namespace views
3872 {
3873 namespace private_views
3874 {
3875 struct zip
3876 {
3877 template <class... Ranges>
3878 constexpr auto operator()(Ranges&&... r) const
3879 {
3880 return zip_view(views::all(etl::forward<Ranges>(r))...);
3881 }
3882 };
3883 } // namespace private_views
3884
3885 inline constexpr private_views::zip zip;
3886 } // namespace views
3887
3888 //*************************************************************************
3892 //*************************************************************************
3893 template <class Fun, class... Ranges>
3894 class zip_transform_iterator
3895 {
3896 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3897
3898 public:
3899
3900 using iterators_type = etl::tuple< typename etl::ranges::private_ranges::iterator_trait< Ranges>::const_iterator...>;
3901 using value_type = etl::invoke_result_t< Fun, typename etl::ranges::private_ranges::iterator_trait<Ranges>::value_type...>;
3902 using difference_type = ptrdiff_t;
3903 using pointer = const value_type*;
3904 using reference = value_type;
3905
3906 using iterator_category = ETL_OR_STD::forward_iterator_tag;
3907
3908 constexpr zip_transform_iterator(Fun f, iterators_type iters)
3909 : _f(f)
3910 , _iters(iters)
3911 {
3912 }
3913
3914 constexpr zip_transform_iterator(const zip_transform_iterator& other) = default;
3915
3916 constexpr zip_transform_iterator& operator=(const zip_transform_iterator& other) = default;
3917
3918 constexpr zip_transform_iterator& operator++()
3919 {
3920 increment(etl::make_index_sequence<sizeof...(Ranges)>{});
3921 return *this;
3922 }
3923
3924 constexpr zip_transform_iterator operator++(int)
3925 {
3926 zip_transform_iterator tmp = *this;
3927 ++(*this);
3928 return tmp;
3929 }
3930
3931 constexpr value_type operator*() const
3932 {
3933 return deref(etl::make_index_sequence<sizeof...(Ranges)>{});
3934 }
3935
3936 friend constexpr bool operator==(const zip_transform_iterator& lhs, const zip_transform_iterator& rhs)
3937 {
3938 return lhs.any_equal(rhs, etl::make_index_sequence<sizeof...(Ranges)>{});
3939 }
3940
3941 friend constexpr bool operator!=(const zip_transform_iterator& lhs, const zip_transform_iterator& rhs)
3942 {
3943 return !(lhs == rhs);
3944 }
3945
3946 private:
3947
3948 template <size_t... Is>
3949 constexpr void increment(etl::index_sequence<Is...>)
3950 {
3951 ((++etl::get<Is>(_iters)), ...);
3952 }
3953
3954 template <size_t... Is>
3955 constexpr value_type deref(etl::index_sequence<Is...>) const
3956 {
3957 return etl::invoke(_f, *etl::get<Is>(_iters)...);
3958 }
3959
3960 // zip terminates when ANY iterator reaches its end (shortest range
3961 // semantics)
3962 template <size_t... Is>
3963 constexpr bool any_equal(const zip_transform_iterator& other, etl::index_sequence<Is...>) const
3964 {
3965 return ((etl::get<Is>(_iters) == etl::get<Is>(other._iters)) || ...);
3966 }
3967
3968 Fun _f;
3969 iterators_type _iters;
3970 };
3971
3972 //*************************************************************************
3978 //*************************************************************************
3979 template <class Fun, class... Ranges>
3980 class zip_transform_view : public etl::ranges::view_interface<zip_transform_view<Fun, Ranges...>>
3981 {
3982 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
3983
3984 public:
3985
3986 using iterator = zip_transform_iterator<Fun, Ranges...>;
3987 using const_iterator = zip_transform_iterator<Fun, Ranges...>;
3988
3989 constexpr zip_transform_view(Fun f, Ranges&&... r)
3990 : _f{f}
3991 , _r{etl::move(r)...}
3992 {
3993 }
3994
3995 zip_transform_view(const zip_transform_view& other) = default;
3996
3997 constexpr const_iterator begin() const
3998 {
3999 return make_begin(etl::make_index_sequence<sizeof...(Ranges)>{});
4000 }
4001
4002 constexpr const_iterator end() const
4003 {
4004 return make_end(etl::make_index_sequence<sizeof...(Ranges)>{});
4005 }
4006
4007 constexpr size_t size() const
4008 {
4009 return get_min_size(etl::make_index_sequence<sizeof...(Ranges)>{});
4010 }
4011
4012 private:
4013
4014 template <size_t... Is>
4015 constexpr const_iterator make_begin(etl::index_sequence<Is...>) const
4016 {
4017 return const_iterator(_f, typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...));
4018 }
4019
4020 template <size_t... Is>
4021 constexpr const_iterator make_end(etl::index_sequence<Is...>) const
4022 {
4023 return const_iterator(_f, typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...));
4024 }
4025
4026 template <size_t... Is>
4027 constexpr size_t get_min_size(etl::index_sequence<Is...>) const
4028 {
4029 size_t sizes[] = {static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(etl::get<Is>(_r)), ETL_OR_STD::cend(etl::get<Is>(_r))))...};
4030 size_t min_val = sizes[0];
4031 for (size_t i = 1; i < sizeof...(Ranges); ++i)
4032 {
4033 if (sizes[i] < min_val)
4034 {
4035 min_val = sizes[i];
4036 }
4037 }
4038 return min_val;
4039 }
4040
4041 Fun _f;
4042 mutable etl::tuple<Ranges...> _r;
4043 };
4044
4045 template <class Fun, class... Ranges>
4046 zip_transform_view(Fun, Ranges&&...) -> zip_transform_view<Fun, views::all_t<Ranges>...>;
4047
4048 namespace views
4049 {
4050 namespace private_views
4051 {
4052 struct zip_transform
4053 {
4054 template <class Fun, class... Ranges>
4055 constexpr auto operator()(Fun&& f, Ranges&&... r) const
4056 {
4057 return zip_transform_view(etl::forward<Fun>(f), views::all(etl::forward<Ranges>(r))...);
4058 }
4059 };
4060 } // namespace private_views
4061
4062 inline constexpr private_views::zip_transform zip_transform;
4063 } // namespace views
4064
4065 //*************************************************************************
4069 //*************************************************************************
4070 template <class I, class S>
4071 class common_iterator
4072 {
4073 public:
4074
4075 using value_type = typename etl::iterator_traits<I>::value_type;
4076 using difference_type = typename etl::iterator_traits<I>::difference_type;
4077 using pointer = typename etl::iterator_traits<I>::pointer;
4078 using reference = typename etl::iterator_traits<I>::reference;
4079 using iterator_category = ETL_OR_STD::input_iterator_tag;
4080
4081 constexpr common_iterator()
4082 : _is_sentinel{false}
4083 , _it{}
4084 , _sentinel{}
4085 {
4086 }
4087
4088 constexpr common_iterator(I it)
4089 : _is_sentinel{false}
4090 , _it{it}
4091 , _sentinel{}
4092 {
4093 }
4094
4095 constexpr common_iterator(S s)
4096 : _is_sentinel{true}
4097 , _it{}
4098 , _sentinel{s}
4099 {
4100 }
4101
4102 constexpr common_iterator(const common_iterator& other)
4103 : _is_sentinel{other._is_sentinel}
4104 , _it{other._it}
4105 , _sentinel{other._sentinel}
4106 {
4107 }
4108
4109 constexpr common_iterator& operator=(const common_iterator& other)
4110 {
4111 _is_sentinel = other._is_sentinel;
4112 _it = other._it;
4113 _sentinel = other._sentinel;
4114 return *this;
4115 }
4116
4117 constexpr decltype(auto) operator*() const
4118 {
4119 return *_it;
4120 }
4121
4122 constexpr decltype(auto) operator*()
4123 {
4124 return *_it;
4125 }
4126
4127 constexpr auto operator->() const
4128 {
4129 return &(*_it);
4130 }
4131
4132 constexpr common_iterator& operator++()
4133 {
4134 ++_it;
4135 return *this;
4136 }
4137
4138 constexpr common_iterator operator++(int)
4139 {
4140 common_iterator tmp = *this;
4141 ++_it;
4142 return tmp;
4143 }
4144
4145 friend constexpr bool operator==(const common_iterator& lhs, const common_iterator& rhs)
4146 {
4147 if (lhs._is_sentinel && rhs._is_sentinel)
4148 {
4149 return true;
4150 }
4151 if (!lhs._is_sentinel && !rhs._is_sentinel)
4152 {
4153 return lhs._it == rhs._it;
4154 }
4155 if (lhs._is_sentinel)
4156 {
4157 return rhs._it == lhs._sentinel;
4158 }
4159 return lhs._it == rhs._sentinel;
4160 }
4161
4162 friend constexpr bool operator!=(const common_iterator& lhs, const common_iterator& rhs)
4163 {
4164 return !(lhs == rhs);
4165 }
4166
4167 private:
4168
4169 bool _is_sentinel;
4170 I _it;
4171 S _sentinel;
4172 };
4173
4174 //*************************************************************************
4177 //*************************************************************************
4178 namespace private_ranges
4179 {
4180 template <typename Range, typename = void>
4181 struct is_common_range : etl::false_type
4182 {
4183 };
4184
4185 template <typename Range>
4186 struct is_common_range<
4187 Range,
4188 etl::enable_if_t< etl::is_same_v< decltype(ETL_OR_STD::begin(etl::declval<Range&>())), decltype(ETL_OR_STD::end(etl::declval<Range&>())) > >>
4189 : etl::true_type
4190 {
4191 };
4192 } // namespace private_ranges
4193
4194 //*************************************************************************
4199 //*************************************************************************
4200 template <class Range, bool IsCommon = private_ranges::is_common_range<Range>::value>
4201 class common_view;
4202
4203 // Specialization for ranges that are already common (begin/end same type)
4204 template <class Range>
4205 class common_view<Range, true> : public etl::ranges::view_interface<common_view<Range, true>>
4206 {
4207 public:
4208
4209 using iterator = decltype(ETL_OR_STD::begin(etl::declval<Range&>()));
4210 using const_iterator = decltype(ETL_OR_STD::cbegin(etl::declval<const Range&>()));
4211 using difference_type = typename etl::iterator_traits<iterator>::difference_type;
4212
4213 constexpr common_view(Range&& r)
4214 : _r{etl::move(r)}
4215 {
4216 }
4217
4218 common_view(const common_view& other) = default;
4219
4220 constexpr Range base() const&
4221 {
4222 return _r;
4223 }
4224
4225 constexpr iterator begin() const
4226 {
4227 return iterator(ETL_OR_STD::begin(_r));
4228 }
4229
4230 constexpr iterator end() const
4231 {
4232 return iterator(ETL_OR_STD::end(_r));
4233 }
4234
4235 constexpr size_t size() const
4236 {
4237 return static_cast<size_t>(etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)));
4238 }
4239
4240 private:
4241
4242 Range _r;
4243 };
4244
4245 // Specialization for ranges that are NOT common (begin/end differ)
4246 template <class Range>
4247 class common_view<Range, false> : public etl::ranges::view_interface<common_view<Range, false>>
4248 {
4249 public:
4250
4251 using base_iterator = decltype(ETL_OR_STD::begin(etl::declval<Range&>()));
4252 using base_sentinel = decltype(ETL_OR_STD::end(etl::declval<Range&>()));
4253 using iterator = common_iterator<base_iterator, base_sentinel>;
4254 using const_iterator = iterator;
4255 using difference_type = typename etl::iterator_traits<base_iterator>::difference_type;
4256
4257 constexpr common_view(Range&& r)
4258 : _r{etl::move(r)}
4259 {
4260 }
4261
4262 common_view(const common_view& other) = default;
4263
4264 constexpr Range base() const&
4265 {
4266 return _r;
4267 }
4268
4269 constexpr iterator begin() const
4270 {
4271 return iterator(ETL_OR_STD::begin(_r));
4272 }
4273
4274 constexpr iterator end() const
4275 {
4276 return iterator(ETL_OR_STD::end(_r));
4277 }
4278
4279 private:
4280
4281 Range _r;
4282 };
4283
4284 template <class Range>
4285 common_view(Range&&) -> common_view<views::all_t<Range>>;
4286
4287 struct common_range_adapter_closure : public range_adapter_closure<common_range_adapter_closure>
4288 {
4289 template <typename Range>
4290 using target_view_type = common_view<Range>;
4291
4292 common_range_adapter_closure() = default;
4293
4294 template <typename Range>
4295 constexpr auto operator()(Range&& r)
4296 {
4297 return common_view(views::all(etl::forward<Range>(r)));
4298 }
4299 };
4300
4301 namespace views
4302 {
4303 namespace private_views
4304 {
4305 struct common : public range_adapter_closure_base
4306 {
4307 template <class Range>
4308 constexpr auto operator()(Range&& r) const
4309 {
4310 return common_view(views::all(etl::forward<Range>(r)));
4311 }
4312
4313 constexpr auto operator()() const
4314 {
4315 return ranges::common_range_adapter_closure();
4316 }
4317 };
4318 } // namespace private_views
4319
4320 inline constexpr private_views::common common;
4321 } // namespace views
4322
4323 //*************************************************************************
4327 //*************************************************************************
4328 template <class Range>
4329 class enumerate_iterator
4330 {
4331 public:
4332
4333 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4334
4335 using base_iterator = typename trait::iterator;
4336 using base_value_type = typename trait::value_type;
4337 using base_reference = decltype(*etl::declval<base_iterator&>());
4338 using value_type = etl::tuple<size_t, base_value_type>;
4339 using difference_type = typename trait::difference_type;
4340 // The second tuple element is a reference into the underlying range, so
4341 // elements remain mutable when the underlying range is non-const, as
4342 // required for std::ranges::enumerate_view.
4343 using reference = etl::tuple<size_t, base_reference>;
4344 using pointer = value_type*;
4345
4346 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4347
4348 enumerate_iterator(base_iterator it, size_t index)
4349 : _it(it)
4350 , _index(index)
4351 {
4352 }
4353
4354 enumerate_iterator(const enumerate_iterator& other)
4355 : _it{other._it}
4356 , _index{other._index}
4357 {
4358 }
4359
4360 enumerate_iterator& operator++()
4361 {
4362 ++_it;
4363 ++_index;
4364 return *this;
4365 }
4366
4367 enumerate_iterator operator++(int)
4368 {
4369 enumerate_iterator tmp = *this;
4370 ++_it;
4371 ++_index;
4372 return tmp;
4373 }
4374
4375 enumerate_iterator& operator=(const enumerate_iterator& other)
4376 {
4377 _it = other._it;
4378 _index = other._index;
4379 return *this;
4380 }
4381
4382 reference operator*() const
4383 {
4384 return reference(_index, *_it);
4385 }
4386
4387 bool operator==(const enumerate_iterator& other) const
4388 {
4389 return other._it == _it;
4390 }
4391
4392 bool operator!=(const enumerate_iterator& other) const
4393 {
4394 return !(*this == other);
4395 }
4396
4397 private:
4398
4399 base_iterator _it;
4400 size_t _index;
4401 };
4402
4403 //*************************************************************************
4407 //*************************************************************************
4408 template <class Range>
4409 class enumerate_view : public etl::ranges::view_interface<enumerate_view<Range>>
4410 {
4411 public:
4412
4413 using iterator = enumerate_iterator<Range>;
4414 using const_iterator = enumerate_iterator<Range>;
4415
4416 enumerate_view(Range&& r)
4417 : _r{etl::move(r)}
4418 {
4419 }
4420
4421 enumerate_view(const enumerate_view& other) = default;
4422
4423 constexpr Range& base() const&
4424 {
4425 return _r;
4426 }
4427
4428 constexpr const_iterator begin() const
4429 {
4430 return const_iterator(ETL_OR_STD::begin(_r), 0);
4431 }
4432
4433 constexpr const_iterator end() const
4434 {
4435 return const_iterator(ETL_OR_STD::end(_r), static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r))));
4436 }
4437
4438 constexpr size_t size() const
4439 {
4440 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4441 }
4442
4443 private:
4444
4445 mutable Range _r;
4446 };
4447
4448 template <class Range>
4449 enumerate_view(Range&&) -> enumerate_view<views::all_t<Range>>;
4450
4451 struct enumerate_range_adapter_closure : public range_adapter_closure<enumerate_range_adapter_closure>
4452 {
4453 template <typename Range>
4454 using target_view_type = enumerate_view<Range>;
4455
4456 enumerate_range_adapter_closure() = default;
4457
4458 template <typename Range>
4459 constexpr auto operator()(Range&& r)
4460 {
4461 return enumerate_view(views::all(etl::forward<Range>(r)));
4462 }
4463 };
4464
4465 namespace views
4466 {
4467 namespace private_views
4468 {
4469 struct enumerate : public range_adapter_closure_base
4470 {
4471 template <class Range>
4472 constexpr auto operator()(Range&& r) const
4473 {
4474 return enumerate_view(views::all(etl::forward<Range>(r)));
4475 }
4476
4477 constexpr auto operator()() const
4478 {
4479 return ranges::enumerate_range_adapter_closure();
4480 }
4481 };
4482 } // namespace private_views
4483
4484 inline constexpr private_views::enumerate enumerate;
4485 } // namespace views
4486
4487 //*************************************************************************
4491 //*************************************************************************
4492 template <class Range, size_t N>
4493 class elements_iterator
4494 {
4495 public:
4496
4497 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4498
4499 using base_iterator = typename trait::iterator;
4500 using base_value_type = typename trait::value_type;
4501 using value_type = etl::tuple_element_t<N, base_value_type>;
4502 using difference_type = typename trait::difference_type;
4503
4504 private:
4505
4506 // Computes the dereference type via ADL get, so that std::pair and
4507 // etl::tuple both resolve correctly. When the underlying range is
4508 // non-const this yields a mutable reference, as required for
4509 // std::ranges::elements_view.
4510 static decltype(auto) deref_element(const base_iterator& it)
4511 {
4512 using etl::get;
4513 return get<N>(*it);
4514 }
4515
4516 public:
4517
4518 using reference = decltype(deref_element(etl::declval<const base_iterator&>()));
4519 using pointer = etl::remove_reference_t<reference>*;
4520
4521 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4522
4523 elements_iterator(base_iterator it)
4524 : _it(it)
4525 {
4526 }
4527
4528 elements_iterator(const elements_iterator& other)
4529 : _it{other._it}
4530 {
4531 }
4532
4533 elements_iterator& operator++()
4534 {
4535 ++_it;
4536 return *this;
4537 }
4538
4539 elements_iterator operator++(int)
4540 {
4541 elements_iterator tmp = *this;
4542 _it++;
4543 return tmp;
4544 }
4545
4546 elements_iterator& operator=(const elements_iterator& other)
4547 {
4548 _it = other._it;
4549 return *this;
4550 }
4551
4552 decltype(auto) operator*() const
4553 {
4554 return deref_element(_it);
4555 }
4556
4557 bool operator==(const elements_iterator& other) const
4558 {
4559 return other._it == _it;
4560 }
4561
4562 bool operator!=(const elements_iterator& other) const
4563 {
4564 return !(*this == other);
4565 }
4566
4567 private:
4568
4569 base_iterator _it;
4570 };
4571
4572 //*************************************************************************
4576 //*************************************************************************
4577 template <class Range, size_t N>
4578 class elements_view : public etl::ranges::view_interface<elements_view<Range, N>>
4579 {
4580 public:
4581
4582 using iterator = elements_iterator<Range, N>;
4583 using const_iterator = elements_iterator<Range, N>;
4584
4585 elements_view(Range&& r)
4586 : _r{etl::move(r)}
4587 {
4588 }
4589
4590 elements_view(const elements_view& other) = default;
4591
4592 constexpr Range& base() const&
4593 {
4594 return _r;
4595 }
4596
4597 constexpr const_iterator begin() const
4598 {
4599 return const_iterator(ETL_OR_STD::begin(_r));
4600 }
4601
4602 constexpr const_iterator end() const
4603 {
4604 return const_iterator(ETL_OR_STD::end(_r));
4605 }
4606
4607 constexpr size_t size() const
4608 {
4609 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4610 }
4611
4612 private:
4613
4614 mutable Range _r;
4615 };
4616
4617 template <class Range, size_t N>
4618 elements_view(Range&&, etl::integral_constant<size_t, N>) -> elements_view<views::all_t<Range>, N>;
4619
4620 template <size_t N>
4621 struct elements_range_adapter_closure : public range_adapter_closure<elements_range_adapter_closure<N>>
4622 {
4623 template <typename Range>
4624 using target_view_type = elements_view<Range, N>;
4625
4626 elements_range_adapter_closure() = default;
4627
4628 template <typename Range>
4629 constexpr auto operator()(Range&& r)
4630 {
4631 return elements_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4632 }
4633 };
4634
4636 template <class Range>
4637 using keys_view = elements_view<Range, 0>;
4638
4640 template <class Range>
4641 using values_view = elements_view<Range, 1>;
4642
4643 namespace views
4644 {
4645 namespace private_views
4646 {
4647 template <size_t N>
4648 struct elements_fn : public range_adapter_closure_base
4649 {
4650 template <class Range>
4651 constexpr auto operator()(Range&& r) const
4652 {
4653 return elements_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4654 }
4655
4656 constexpr auto operator()() const
4657 {
4658 return ranges::elements_range_adapter_closure<N>();
4659 }
4660 };
4661 } // namespace private_views
4662
4663 template <size_t N>
4664 inline constexpr private_views::elements_fn<N> elements{};
4665
4666 inline constexpr private_views::elements_fn<0> keys{};
4667 inline constexpr private_views::elements_fn<1> values{};
4668 } // namespace views
4669
4670 //*************************************************************************
4672 //*************************************************************************
4673 namespace private_ranges
4674 {
4675 template <typename T, size_t N, typename = etl::make_index_sequence<N>>
4676 struct repeat_tuple;
4677
4678 template <typename T, size_t N, size_t... Is>
4679 struct repeat_tuple<T, N, etl::index_sequence<Is...>>
4680 {
4681 template <size_t>
4682 using always = T;
4683
4684 using type = etl::tuple<always<Is>...>;
4685 };
4686
4687 template <typename T, size_t N>
4688 using repeat_tuple_t = typename repeat_tuple<T, N>::type;
4689
4692 template <typename Fun, typename T, size_t N, typename = etl::make_index_sequence<N>>
4693 struct repeat_invoke_result;
4694
4695 template <typename Fun, typename T, size_t N, size_t... Is>
4696 struct repeat_invoke_result<Fun, T, N, etl::index_sequence<Is...>>
4697 {
4698 template <size_t>
4699 using always = T;
4700
4701 using type = etl::invoke_result_t<Fun, always<Is>...>;
4702 };
4703
4704 template <typename Fun, typename T, size_t N>
4705 using repeat_invoke_result_t = typename repeat_invoke_result<Fun, T, N>::type;
4706 } // namespace private_ranges
4707
4708 //*************************************************************************
4713 //*************************************************************************
4714 template <class Range, size_t N>
4715 class adjacent_iterator
4716 {
4717 static_assert(N > 0, "adjacent window size must be > 0");
4718
4719 public:
4720
4721 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4722
4723 using base_iterator = typename trait::iterator;
4724 using base_value_type = typename trait::value_type;
4725 using base_reference = decltype(*etl::declval<base_iterator&>());
4726 using value_type = private_ranges::repeat_tuple_t<base_value_type, N>;
4727 using difference_type = typename trait::difference_type;
4728 // Each tuple element is a reference into the underlying range, so the
4729 // window elements remain mutable when the underlying range is non-const,
4730 // as required for std::ranges::adjacent_view.
4731 using reference = private_ranges::repeat_tuple_t<base_reference, N>;
4732 using pointer = value_type*;
4733
4734 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4735
4737 template <size_t... Is>
4738 constexpr adjacent_iterator(base_iterator first, base_iterator last, etl::index_sequence<Is...>)
4739 : _iters{advance_copy(first, last, Is)...}
4740 , _end{last}
4741 {
4742 }
4743
4744 constexpr adjacent_iterator(const adjacent_iterator& other) = default;
4745
4746 constexpr adjacent_iterator& operator=(const adjacent_iterator& other) = default;
4747
4748 constexpr adjacent_iterator& operator++()
4749 {
4750 increment(etl::make_index_sequence<N>{});
4751 return *this;
4752 }
4753
4754 constexpr adjacent_iterator operator++(int)
4755 {
4756 adjacent_iterator tmp = *this;
4757 ++(*this);
4758 return tmp;
4759 }
4760
4761 constexpr reference operator*() const
4762 {
4763 return deref(etl::make_index_sequence<N>{});
4764 }
4765
4766 friend constexpr bool operator==(const adjacent_iterator& lhs, const adjacent_iterator& rhs)
4767 {
4768 // Compare the last iterator in the window (index N-1).
4769 // When it reaches end, the window is exhausted.
4770 return lhs._iters[N - 1] == rhs._iters[N - 1];
4771 }
4772
4773 friend constexpr bool operator!=(const adjacent_iterator& lhs, const adjacent_iterator& rhs)
4774 {
4775 return !(lhs == rhs);
4776 }
4777
4778 private:
4779
4780 static constexpr base_iterator advance_copy(base_iterator it, base_iterator last, size_t n)
4781 {
4782 for (size_t i = 0; i < n && it != last; ++i)
4783 {
4784 ++it;
4785 }
4786 return it;
4787 }
4788
4789 template <size_t... Is>
4790 constexpr void increment(etl::index_sequence<Is...>)
4791 {
4792 ((void)((_iters[Is] != _end) ? (void)++_iters[Is] : (void)0), ...);
4793 }
4794
4795 template <size_t... Is>
4796 constexpr reference deref(etl::index_sequence<Is...>) const
4797 {
4798 return reference(*_iters[Is]...);
4799 }
4800
4801 base_iterator _iters[N];
4802 base_iterator _end;
4803 };
4804
4805 //*************************************************************************
4812 //*************************************************************************
4813 template <class Range, size_t N>
4814 class adjacent_view : public etl::ranges::view_interface<adjacent_view<Range, N>>
4815 {
4816 static_assert(N > 0, "adjacent window size must be > 0");
4817
4818 public:
4819
4820 using iterator = adjacent_iterator<Range, N>;
4821 using const_iterator = adjacent_iterator<Range, N>;
4822
4823 constexpr adjacent_view(Range&& r)
4824 : _r{etl::move(r)}
4825 {
4826 }
4827
4828 adjacent_view(const adjacent_view& other) = default;
4829
4830 constexpr Range& base() const&
4831 {
4832 return _r;
4833 }
4834
4835 constexpr const_iterator begin() const
4836 {
4837 return const_iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
4838 }
4839
4840 constexpr const_iterator end() const
4841 {
4842 // The end iterator has all N internal iterators at the end position.
4843 return const_iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
4844 }
4845
4846 constexpr size_t size() const
4847 {
4848 auto total = static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
4849 return (total >= N) ? (total - N + 1) : 0;
4850 }
4851
4852 private:
4853
4854 mutable Range _r;
4855 };
4856
4857 template <class Range, size_t N>
4858 adjacent_view(Range&&, etl::integral_constant<size_t, N>) -> adjacent_view<views::all_t<Range>, N>;
4859
4860 template <size_t N>
4861 struct adjacent_range_adapter_closure : public range_adapter_closure<adjacent_range_adapter_closure<N>>
4862 {
4863 template <typename Range>
4864 using target_view_type = adjacent_view<Range, N>;
4865
4866 adjacent_range_adapter_closure() = default;
4867
4868 template <typename Range>
4869 constexpr auto operator()(Range&& r)
4870 {
4871 return adjacent_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4872 }
4873 };
4874
4875 namespace views
4876 {
4877 namespace private_views
4878 {
4879 template <size_t N>
4880 struct adjacent_fn : public range_adapter_closure_base
4881 {
4882 template <class Range>
4883 constexpr auto operator()(Range&& r) const
4884 {
4885 return adjacent_view<views::all_t<Range>, N>(views::all(etl::forward<Range>(r)));
4886 }
4887
4888 constexpr auto operator()() const
4889 {
4890 return ranges::adjacent_range_adapter_closure<N>();
4891 }
4892 };
4893 } // namespace private_views
4894
4895 template <size_t N>
4896 inline constexpr private_views::adjacent_fn<N> adjacent{};
4897
4899 inline constexpr private_views::adjacent_fn<2> pairwise{};
4900 } // namespace views
4901
4902 //*************************************************************************
4907 //*************************************************************************
4908 template <class Range, class Fun, size_t N>
4909 class adjacent_transform_iterator
4910 {
4911 static_assert(N > 0, "adjacent window size must be > 0");
4912
4913 public:
4914
4915 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
4916
4917 using base_iterator = typename trait::const_iterator;
4918 using base_value_type = typename trait::value_type;
4919 using value_type = private_ranges::repeat_invoke_result_t<Fun, base_value_type, N>;
4920 using difference_type = typename trait::difference_type;
4921 using pointer = const value_type*;
4922 using reference = value_type;
4923
4924 using iterator_category = ETL_OR_STD::forward_iterator_tag;
4925
4928 template <size_t... Is>
4929 constexpr adjacent_transform_iterator(Fun f, base_iterator first, base_iterator last, etl::index_sequence<Is...>)
4930 : _f{f}
4931 , _iters{advance_copy(first, last, Is)...}
4932 , _end{last}
4933 {
4934 }
4935
4936 constexpr adjacent_transform_iterator(const adjacent_transform_iterator& other) = default;
4937
4938 constexpr adjacent_transform_iterator& operator=(const adjacent_transform_iterator& other) = default;
4939
4940 constexpr adjacent_transform_iterator& operator++()
4941 {
4942 increment(etl::make_index_sequence<N>{});
4943 return *this;
4944 }
4945
4946 constexpr adjacent_transform_iterator operator++(int)
4947 {
4948 adjacent_transform_iterator tmp = *this;
4949 ++(*this);
4950 return tmp;
4951 }
4952
4953 constexpr value_type operator*() const
4954 {
4955 return deref(etl::make_index_sequence<N>{});
4956 }
4957
4958 friend constexpr bool operator==(const adjacent_transform_iterator& lhs, const adjacent_transform_iterator& rhs)
4959 {
4960 // Compare the last iterator in the window (index N-1).
4961 // When it reaches end, the window is exhausted.
4962 return lhs._iters[N - 1] == rhs._iters[N - 1];
4963 }
4964
4965 friend constexpr bool operator!=(const adjacent_transform_iterator& lhs, const adjacent_transform_iterator& rhs)
4966 {
4967 return !(lhs == rhs);
4968 }
4969
4970 private:
4971
4972 static constexpr base_iterator advance_copy(base_iterator it, base_iterator last, size_t n)
4973 {
4974 for (size_t i = 0; i < n && it != last; ++i)
4975 {
4976 ++it;
4977 }
4978 return it;
4979 }
4980
4981 template <size_t... Is>
4982 constexpr void increment(etl::index_sequence<Is...>)
4983 {
4984 ((void)((_iters[Is] != _end) ? (void)++_iters[Is] : (void)0), ...);
4985 }
4986
4987 template <size_t... Is>
4988 constexpr value_type deref(etl::index_sequence<Is...>) const
4989 {
4990 return etl::invoke(_f, *_iters[Is]...);
4991 }
4992
4993 Fun _f;
4994 base_iterator _iters[N];
4995 base_iterator _end;
4996 };
4997
4998 //*************************************************************************
5006 //*************************************************************************
5007 template <class Range, class Fun, size_t N>
5008 class adjacent_transform_view : public etl::ranges::view_interface< adjacent_transform_view<Range, Fun, N>>
5009 {
5010 static_assert(N > 0, "adjacent window size must be > 0");
5011
5012 public:
5013
5014 using iterator = adjacent_transform_iterator<Range, Fun, N>;
5015 using const_iterator = adjacent_transform_iterator<Range, Fun, N>;
5016
5017 constexpr adjacent_transform_view(Fun f, Range&& r)
5018 : _f{f}
5019 , _r{etl::move(r)}
5020 {
5021 }
5022
5023 adjacent_transform_view(const adjacent_transform_view& other) = default;
5024
5025 constexpr Range& base() const&
5026 {
5027 return _r;
5028 }
5029
5030 constexpr const_iterator begin() const
5031 {
5032 return const_iterator(_f, ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
5033 }
5034
5035 constexpr const_iterator end() const
5036 {
5037 // The end iterator has all N internal iterators at the end position.
5038 return const_iterator(_f, ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), etl::make_index_sequence<N>{});
5039 }
5040
5041 constexpr size_t size() const
5042 {
5043 auto total = static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
5044 return (total >= N) ? (total - N + 1) : 0;
5045 }
5046
5047 private:
5048
5049 Fun _f;
5050 mutable Range _r;
5051 };
5052
5053 template <class Fun, class Range, size_t N>
5054 adjacent_transform_view(Fun, Range&&, etl::integral_constant<size_t, N>) -> adjacent_transform_view<views::all_t<Range>, Fun, N>;
5055
5056 template <size_t N, typename Fun>
5057 struct adjacent_transform_range_adapter_closure : public range_adapter_closure< adjacent_transform_range_adapter_closure<N, Fun>>
5058 {
5059 template <typename Range>
5060 using target_view_type = adjacent_transform_view<Range, Fun, N>;
5061
5062 adjacent_transform_range_adapter_closure(Fun f)
5063 : _f{f}
5064 {
5065 }
5066
5067 template <typename Range>
5068 constexpr auto operator()(Range&& r)
5069 {
5070 return adjacent_transform_view<views::all_t<Range>, Fun, N>(_f, views::all(etl::forward<Range>(r)));
5071 }
5072
5073 Fun _f;
5074 };
5075
5076 namespace views
5077 {
5078 namespace private_views
5079 {
5080 template <size_t N>
5081 struct adjacent_transform_fn
5082 {
5083 template <class Range, typename Fun>
5084 constexpr auto operator()(Range&& r, Fun&& f) const
5085 {
5086 return adjacent_transform_view<views::all_t<Range>, etl::decay_t<Fun>, N>(etl::forward<Fun>(f), views::all(etl::forward<Range>(r)));
5087 }
5088
5089 template <typename Fun>
5090 constexpr auto operator()(Fun&& f) const
5091 {
5092 return ranges::adjacent_transform_range_adapter_closure< N, etl::decay_t<Fun>>(etl::forward<Fun>(f));
5093 }
5094 };
5095 } // namespace private_views
5096
5097 template <size_t N>
5098 inline constexpr private_views::adjacent_transform_fn<N> adjacent_transform{};
5099
5101 inline constexpr private_views::adjacent_transform_fn<2> pairwise_transform{};
5102 } // namespace views
5103
5104 //*************************************************************************
5106 //*************************************************************************
5107 template <class Range>
5108 class chunk_iterator
5109 {
5110 public:
5111
5112 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5113
5114 using inner_iterator = typename trait::iterator;
5115 using const_inner_iterator = typename trait::const_iterator;
5116 using difference_type = typename trait::difference_type;
5117
5118 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5119
5120 using value_type = etl::ranges::subrange<inner_iterator>;
5121 using pointer = value_type*;
5122 using reference = value_type;
5123
5124 chunk_iterator(inner_iterator it, inner_iterator it_end, difference_type chunk_size)
5125 : _it(it)
5126 , _it_end(it_end)
5127 , _chunk_size(chunk_size)
5128 {
5129 }
5130
5131 chunk_iterator(const chunk_iterator& other) = default;
5132
5133 chunk_iterator& operator=(const chunk_iterator& other) = default;
5134
5135 chunk_iterator& operator++()
5136 {
5137 difference_type remaining = etl::distance(_it, _it_end);
5138 difference_type step = (_chunk_size < remaining) ? _chunk_size : remaining;
5139 etl::advance(_it, step);
5140 return *this;
5141 }
5142
5143 chunk_iterator operator++(int)
5144 {
5145 chunk_iterator tmp{*this};
5146 ++(*this);
5147 return tmp;
5148 }
5149
5150 value_type operator*() const
5151 {
5152 difference_type remaining = etl::distance(_it, _it_end);
5153 difference_type step = (_chunk_size < remaining) ? _chunk_size : remaining;
5154 inner_iterator chunk_end = _it;
5155 etl::advance(chunk_end, step);
5156 return value_type(_it, chunk_end);
5157 }
5158
5159 constexpr bool operator==(const chunk_iterator& other) const
5160 {
5161 return _it == other._it;
5162 }
5163
5164 constexpr bool operator!=(const chunk_iterator& other) const
5165 {
5166 return !(*this == other);
5167 }
5168
5169 private:
5170
5171 inner_iterator _it;
5172 inner_iterator _it_end;
5173 difference_type _chunk_size;
5174 };
5175
5176 //*************************************************************************
5180 //*************************************************************************
5181 template <class Range>
5182 class chunk_view : public etl::ranges::view_interface<chunk_view<Range>>
5183 {
5184 public:
5185
5186 using iterator = chunk_iterator<Range>;
5187 using const_iterator = chunk_iterator<Range>;
5188 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
5189
5190 constexpr chunk_view(Range&& r, difference_type chunk_size)
5191 : _r{etl::move(r)}
5192 , _chunk_size{chunk_size}
5193 {
5194 }
5195
5196 chunk_view(const chunk_view& other) = default;
5197
5198 constexpr Range base() const&
5199 {
5200 return _r;
5201 }
5202
5203 constexpr iterator begin() const
5204 {
5205 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _chunk_size);
5206 }
5207
5208 constexpr iterator end() const
5209 {
5210 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _chunk_size);
5211 }
5212
5213 private:
5214
5215 Range _r;
5216 difference_type _chunk_size;
5217 };
5218
5219 template <class Range>
5220 chunk_view(Range&&, typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type) -> chunk_view<views::all_t<Range>>;
5221
5222 struct chunk_range_adapter_closure : public range_adapter_closure<chunk_range_adapter_closure>
5223 {
5224 template <typename Range>
5225 using target_view_type = chunk_view<Range>;
5226
5227 template <class DifferenceType>
5228 constexpr chunk_range_adapter_closure(DifferenceType chunk_size)
5229 : _chunk_size{static_cast<size_t>(chunk_size)}
5230 {
5231 }
5232
5233 template <typename Range>
5234 constexpr auto operator()(Range&& r) const
5235 {
5236 return chunk_view(views::all(etl::forward<Range>(r)), static_cast< typename chunk_view<views::all_t<Range>>::difference_type>(_chunk_size));
5237 }
5238
5239 const size_t _chunk_size;
5240 };
5241
5242 namespace views
5243 {
5244 namespace private_views
5245 {
5246 struct chunk
5247 {
5248 template <class Range>
5249 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> chunk_size) const
5250 {
5251 return chunk_view(views::all(etl::forward<Range>(r)), chunk_size);
5252 }
5253
5254 template <class DifferenceType>
5255 constexpr auto operator()(DifferenceType chunk_size) const
5256 {
5257 return ranges::chunk_range_adapter_closure(chunk_size);
5258 }
5259 };
5260 } // namespace private_views
5261
5262 inline constexpr private_views::chunk chunk;
5263 } // namespace views
5264
5265 //*************************************************************************
5268 //*************************************************************************
5269 template <class Range>
5270 class slide_iterator
5271 {
5272 public:
5273
5274 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5275
5276 using inner_iterator = typename trait::iterator;
5277 using const_inner_iterator = typename trait::const_iterator;
5278 using difference_type = typename trait::difference_type;
5279
5280 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5281
5282 using value_type = etl::ranges::subrange<inner_iterator>;
5283 using pointer = value_type*;
5284 using reference = value_type;
5285
5286 slide_iterator(inner_iterator it, inner_iterator it_end, difference_type window_size)
5287 : _it(it)
5288 , _it_end(it_end)
5289 , _window_size(window_size)
5290 {
5291 }
5292
5293 slide_iterator(const slide_iterator& other) = default;
5294
5295 slide_iterator& operator=(const slide_iterator& other) = default;
5296
5297 slide_iterator& operator++()
5298 {
5299 ++_it;
5300 return *this;
5301 }
5302
5303 slide_iterator operator++(int)
5304 {
5305 slide_iterator tmp{*this};
5306 ++(*this);
5307 return tmp;
5308 }
5309
5310 value_type operator*() const
5311 {
5312 inner_iterator window_end = _it;
5313 etl::advance(window_end, _window_size);
5314 return value_type(_it, window_end);
5315 }
5316
5317 constexpr bool operator==(const slide_iterator& other) const
5318 {
5319 return _it == other._it;
5320 }
5321
5322 constexpr bool operator!=(const slide_iterator& other) const
5323 {
5324 return !(*this == other);
5325 }
5326
5327 private:
5328
5329 inner_iterator _it;
5330 inner_iterator _it_end;
5331 difference_type _window_size;
5332 };
5333
5334 //*************************************************************************
5340 //*************************************************************************
5341 template <class Range>
5342 class slide_view : public etl::ranges::view_interface<slide_view<Range>>
5343 {
5344 public:
5345
5346 using iterator = slide_iterator<Range>;
5347 using const_iterator = slide_iterator<Range>;
5348 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
5349
5350 constexpr slide_view(Range&& r, difference_type window_size)
5351 : _r{etl::move(r)}
5352 , _window_size{window_size}
5353 {
5354 }
5355
5356 slide_view(const slide_view& other) = default;
5357
5358 constexpr Range base() const&
5359 {
5360 return _r;
5361 }
5362
5363 constexpr iterator begin() const
5364 {
5365 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _window_size);
5366 }
5367
5368 constexpr iterator end() const
5369 {
5370 auto total = static_cast<difference_type>(etl::distance(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r)));
5371 if (total < _window_size)
5372 {
5373 // Empty view: begin == end
5374 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _window_size);
5375 }
5376 auto end_it = ETL_OR_STD::begin(_r);
5377 etl::advance(end_it, total - _window_size + 1);
5378 return iterator(end_it, ETL_OR_STD::end(_r), _window_size);
5379 }
5380
5381 constexpr size_t size() const
5382 {
5383 auto total = static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
5384 return (total >= static_cast<size_t>(_window_size)) ? (total - static_cast<size_t>(_window_size) + 1) : 0;
5385 }
5386
5387 private:
5388
5389 Range _r;
5390 difference_type _window_size;
5391 };
5392
5393 template <class Range>
5394 slide_view(Range&&, typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type) -> slide_view<views::all_t<Range>>;
5395
5396 struct slide_range_adapter_closure : public range_adapter_closure<slide_range_adapter_closure>
5397 {
5398 template <typename Range>
5399 using target_view_type = slide_view<Range>;
5400
5401 template <class DifferenceType>
5402 constexpr slide_range_adapter_closure(DifferenceType window_size)
5403 : _window_size{static_cast<size_t>(window_size)}
5404 {
5405 }
5406
5407 template <typename Range>
5408 constexpr auto operator()(Range&& r) const
5409 {
5410 return slide_view(views::all(etl::forward<Range>(r)), static_cast< typename slide_view<views::all_t<Range>>::difference_type>(_window_size));
5411 }
5412
5413 const size_t _window_size;
5414 };
5415
5416 namespace views
5417 {
5418 namespace private_views
5419 {
5420 struct slide
5421 {
5422 template <class Range>
5423 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> window_size) const
5424 {
5425 return slide_view(views::all(etl::forward<Range>(r)), window_size);
5426 }
5427
5428 template <class DifferenceType>
5429 constexpr auto operator()(DifferenceType window_size) const
5430 {
5431 return ranges::slide_range_adapter_closure(window_size);
5432 }
5433 };
5434 } // namespace private_views
5435
5436 inline constexpr private_views::slide slide;
5437 } // namespace views
5438
5439 //*************************************************************************
5444 //*************************************************************************
5445 template <class Range, class Pred>
5446 class chunk_by_iterator
5447 {
5448 public:
5449
5450 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5451
5452 using inner_iterator = typename trait::iterator;
5453 using const_inner_iterator = typename trait::const_iterator;
5454 using difference_type = typename trait::difference_type;
5455
5456 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5457
5458 using value_type = etl::ranges::subrange<inner_iterator>;
5459 using pointer = value_type*;
5460 using reference = value_type;
5461
5462 chunk_by_iterator(inner_iterator it, inner_iterator it_end, const Pred& pred)
5463 : _it(it)
5464 , _it_end(it_end)
5465 , _pred(pred)
5466 {
5467 _chunk_end = find_next_chunk_end();
5468 }
5469
5470 chunk_by_iterator(const chunk_by_iterator& other) = default;
5471
5472 chunk_by_iterator& operator=(const chunk_by_iterator& other) = default;
5473
5474 chunk_by_iterator& operator++()
5475 {
5476 _it = _chunk_end;
5477 _chunk_end = find_next_chunk_end();
5478 return *this;
5479 }
5480
5481 chunk_by_iterator operator++(int)
5482 {
5483 chunk_by_iterator tmp{*this};
5484 ++(*this);
5485 return tmp;
5486 }
5487
5488 value_type operator*() const
5489 {
5490 return value_type(_it, _chunk_end);
5491 }
5492
5493 constexpr bool operator==(const chunk_by_iterator& other) const
5494 {
5495 return _it == other._it;
5496 }
5497
5498 constexpr bool operator!=(const chunk_by_iterator& other) const
5499 {
5500 return !(*this == other);
5501 }
5502
5503 private:
5504
5505 inner_iterator find_next_chunk_end() const
5506 {
5507 if (_it == _it_end)
5508 {
5509 return _it_end;
5510 }
5511
5512 inner_iterator it_prev = _it;
5513 inner_iterator it_curr = _it;
5514 ++it_curr;
5515
5516 while (it_curr != _it_end)
5517 {
5518 if (!_pred(*it_prev, *it_curr))
5519 {
5520 return it_curr;
5521 }
5522 it_prev = it_curr;
5523 ++it_curr;
5524 }
5525
5526 return _it_end;
5527 }
5528
5529 inner_iterator _it;
5530 inner_iterator _it_end;
5531 inner_iterator _chunk_end;
5532 Pred _pred;
5533 };
5534
5535 //*************************************************************************
5540 //*************************************************************************
5541 template <class Range, class Pred>
5542 class chunk_by_view : public etl::ranges::view_interface<chunk_by_view<Range, Pred>>
5543 {
5544 public:
5545
5546 using iterator = chunk_by_iterator<Range, Pred>;
5547 using const_iterator = chunk_by_iterator<Range, Pred>;
5548
5549 chunk_by_view(Range&& r, const Pred& pred)
5550 : _r{etl::move(r)}
5551 , _pred{pred}
5552 {
5553 }
5554
5555 chunk_by_view(const chunk_by_view& other) = default;
5556
5557 constexpr Range base() const&
5558 {
5559 return _r;
5560 }
5561
5562 constexpr const Pred& pred() const
5563 {
5564 return _pred;
5565 }
5566
5567 constexpr const_iterator begin() const
5568 {
5569 return const_iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _pred);
5570 }
5571
5572 constexpr const_iterator end() const
5573 {
5574 return const_iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _pred);
5575 }
5576
5577 private:
5578
5579 Range _r;
5580 const Pred _pred;
5581 };
5582
5583 template <class Range, typename Pred>
5584 chunk_by_view(Range&&, Pred) -> chunk_by_view<views::all_t<Range>, Pred>;
5585
5586 template <typename Pred>
5587 struct chunk_by_range_adapter_closure : public range_adapter_closure<chunk_by_range_adapter_closure<Pred>>
5588 {
5589 template <typename Range>
5590 using target_view_type = chunk_by_view<Range, Pred>;
5591
5592 chunk_by_range_adapter_closure(const Pred& p)
5593 : _p{p}
5594 {
5595 }
5596
5597 template <typename Range>
5598 constexpr auto operator()(Range&& r) const
5599 {
5600 return chunk_by_view(views::all(etl::forward<Range>(r)), _p);
5601 }
5602
5603 const Pred _p;
5604 };
5605
5606 namespace views
5607 {
5608 namespace private_views
5609 {
5610 struct chunk_by
5611 {
5612 template <class Range, typename Pred>
5613 constexpr auto operator()(Range&& r, const Pred& p) const
5614 {
5615 return chunk_by_view(views::all(etl::forward<Range>(r)), p);
5616 }
5617
5618 template <typename Pred>
5619 constexpr auto operator()(const Pred& p) const
5620 {
5621 return ranges::chunk_by_range_adapter_closure<Pred>(p);
5622 }
5623 };
5624 } // namespace private_views
5625
5626 inline constexpr private_views::chunk_by chunk_by;
5627 } // namespace views
5628
5629 //*************************************************************************
5632 //*************************************************************************
5633 template <class Range>
5634 class stride_iterator
5635 {
5636 public:
5637
5638 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
5639
5640 using inner_iterator = typename trait::iterator;
5641 using const_inner_iterator = typename trait::const_iterator;
5642 using difference_type = typename trait::difference_type;
5643
5644 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5645
5646 using value_type = typename trait::value_type;
5647 using reference = decltype(*etl::declval<inner_iterator&>());
5648 using pointer = etl::remove_reference_t<reference>*;
5649
5650 constexpr stride_iterator(inner_iterator it, inner_iterator it_end, difference_type stride_n)
5651 : _it(it)
5652 , _it_end(it_end)
5653 , _stride_n(stride_n)
5654 {
5655 }
5656
5657 stride_iterator(const stride_iterator& other) = default;
5658
5659 stride_iterator& operator=(const stride_iterator& other) = default;
5660
5661 constexpr stride_iterator& operator++()
5662 {
5663 difference_type remaining = etl::distance(_it, _it_end);
5664 difference_type step = (_stride_n < remaining) ? _stride_n : remaining;
5665 etl::advance(_it, step);
5666 return *this;
5667 }
5668
5669 constexpr stride_iterator operator++(int)
5670 {
5671 stride_iterator tmp{*this};
5672 ++(*this);
5673 return tmp;
5674 }
5675
5676 constexpr decltype(auto) operator*() const
5677 {
5678 return *_it;
5679 }
5680
5681 constexpr pointer operator->() const
5682 {
5683 return &(*_it);
5684 }
5685
5686 constexpr bool operator==(const stride_iterator& other) const
5687 {
5688 return _it == other._it;
5689 }
5690
5691 constexpr bool operator!=(const stride_iterator& other) const
5692 {
5693 return !(*this == other);
5694 }
5695
5696 private:
5697
5698 mutable inner_iterator _it;
5699 inner_iterator _it_end;
5700 difference_type _stride_n;
5701 };
5702
5703 //*************************************************************************
5706 //*************************************************************************
5707 template <class Range>
5708 class stride_view : public etl::ranges::view_interface<stride_view<Range>>
5709 {
5710 public:
5711
5712 using iterator = stride_iterator<Range>;
5713 using const_iterator = stride_iterator<Range>;
5714 using difference_type = typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type;
5715
5716 constexpr stride_view(Range&& r, difference_type stride_n)
5717 : _r{etl::move(r)}
5718 , _stride_n{stride_n}
5719 {
5720 }
5721
5722 stride_view(const stride_view& other) = default;
5723
5724 constexpr Range base() const&
5725 {
5726 return _r;
5727 }
5728
5729 constexpr iterator begin() const
5730 {
5731 return iterator(ETL_OR_STD::begin(_r), ETL_OR_STD::end(_r), _stride_n);
5732 }
5733
5734 constexpr iterator end() const
5735 {
5736 return iterator(ETL_OR_STD::end(_r), ETL_OR_STD::end(_r), _stride_n);
5737 }
5738
5739 private:
5740
5741 Range _r;
5742 difference_type _stride_n;
5743 };
5744
5745 template <class Range>
5746 stride_view(Range&&, typename etl::ranges::private_ranges::iterator_trait< Range>::difference_type) -> stride_view<views::all_t<Range>>;
5747
5748 struct stride_range_adapter_closure : public range_adapter_closure<stride_range_adapter_closure>
5749 {
5750 template <typename Range>
5751 using target_view_type = stride_view<Range>;
5752
5753 template <class DifferenceType>
5754 constexpr stride_range_adapter_closure(DifferenceType stride_n)
5755 : _stride_n{static_cast<size_t>(stride_n)}
5756 {
5757 }
5758
5759 template <typename Range>
5760 constexpr auto operator()(Range&& r) const
5761 {
5762 return stride_view(views::all(etl::forward<Range>(r)), static_cast< typename stride_view<views::all_t<Range>>::difference_type>(_stride_n));
5763 }
5764
5765 const size_t _stride_n;
5766 };
5767
5768 namespace views
5769 {
5770 namespace private_views
5771 {
5772 struct stride
5773 {
5774 template <class Range>
5775 constexpr auto operator()(Range&& r, ranges::range_difference_t<Range> stride_n) const
5776 {
5777 return stride_view(views::all(etl::forward<Range>(r)), stride_n);
5778 }
5779
5780 template <class DifferenceType>
5781 constexpr auto operator()(DifferenceType stride_n) const
5782 {
5783 return ranges::stride_range_adapter_closure(stride_n);
5784 }
5785 };
5786 } // namespace private_views
5787
5788 inline constexpr private_views::stride stride;
5789 } // namespace views
5790
5791 //*************************************************************************
5797 //*************************************************************************
5798 template <class... Ranges>
5799 class cartesian_product_iterator
5800 {
5801 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
5802
5803 public:
5804
5805 using iterators_type = etl::tuple< typename etl::ranges::private_ranges::iterator_trait< Ranges>::const_iterator...>;
5806 using value_type = etl::tuple<typename etl::ranges::private_ranges::iterator_trait< Ranges>::value_type...>;
5807 using difference_type = ptrdiff_t;
5808 using pointer = const value_type*;
5809 using reference = value_type;
5810
5811 using iterator_category = ETL_OR_STD::forward_iterator_tag;
5812
5813 constexpr cartesian_product_iterator(iterators_type current, iterators_type begins, iterators_type ends, bool is_end = false)
5814 : _current_it(current)
5815 , _begins(begins)
5816 , _ends(ends)
5817 , _is_end(is_end)
5818 {
5819 }
5820
5821 constexpr cartesian_product_iterator(const cartesian_product_iterator& other) = default;
5822
5823 constexpr cartesian_product_iterator& operator=(const cartesian_product_iterator& other) = default;
5824
5825 constexpr cartesian_product_iterator& operator++()
5826 {
5827 increment();
5828 return *this;
5829 }
5830
5831 constexpr cartesian_product_iterator operator++(int)
5832 {
5833 cartesian_product_iterator tmp = *this;
5834 ++(*this);
5835 return tmp;
5836 }
5837
5838 constexpr value_type operator*() const
5839 {
5840 return deref(etl::make_index_sequence<sizeof...(Ranges)>{});
5841 }
5842
5843 friend constexpr bool operator==(const cartesian_product_iterator& lhs, const cartesian_product_iterator& rhs)
5844 {
5845 return lhs._is_end == rhs._is_end && (lhs._is_end || lhs.all_equal(rhs, etl::make_index_sequence<sizeof...(Ranges)>{}));
5846 }
5847
5848 friend constexpr bool operator!=(const cartesian_product_iterator& lhs, const cartesian_product_iterator& rhs)
5849 {
5850 return !(lhs == rhs);
5851 }
5852
5853 private:
5854
5855 // Increment with carry: increment the last range, and carry over to the
5856 // previous range when a range wraps around
5857 constexpr void increment()
5858 {
5859 if (_is_end)
5860 return;
5861 increment_at<sizeof...(Ranges) - 1>();
5862 }
5863
5864 template <size_t I>
5865 constexpr etl::enable_if_t<(I > 0)> increment_at()
5866 {
5867 auto& it = etl::get<I>(_current_it);
5868 ++it;
5869 if (it == etl::get<I>(_ends))
5870 {
5871 it = etl::get<I>(_begins);
5872 increment_at<I - 1>();
5873 }
5874 }
5875
5876 template <size_t I>
5877 constexpr etl::enable_if_t<(I == 0)> increment_at()
5878 {
5879 auto& it = etl::get<0>(_current_it);
5880 ++it;
5881 if (it == etl::get<0>(_ends))
5882 {
5883 _is_end = true;
5884 }
5885 }
5886
5887 template <size_t... Is>
5888 constexpr value_type deref(etl::index_sequence<Is...>) const
5889 {
5890 return value_type(*etl::get<Is>(_current_it)...);
5891 }
5892
5893 template <size_t... Is>
5894 constexpr bool all_equal(const cartesian_product_iterator& other, etl::index_sequence<Is...>) const
5895 {
5896 return ((etl::get<Is>(_current_it) == etl::get<Is>(other._current_it)) && ...);
5897 }
5898
5899 iterators_type _current_it;
5900 iterators_type _begins;
5901 iterators_type _ends;
5902 bool _is_end;
5903 };
5904
5905 //*************************************************************************
5912 //*************************************************************************
5913 template <class... Ranges>
5914 class cartesian_product_view : public etl::ranges::view_interface<cartesian_product_view<Ranges...>>
5915 {
5916 static_assert(sizeof...(Ranges) > 0, "Type list must be non-empty");
5917
5918 public:
5919
5920 using iterator = cartesian_product_iterator<Ranges...>;
5921 using const_iterator = cartesian_product_iterator<Ranges...>;
5922
5923 constexpr cartesian_product_view(Ranges&&... r)
5924 : _r{etl::move(r)...}
5925 {
5926 }
5927
5928 cartesian_product_view(const cartesian_product_view& other) = default;
5929
5930 constexpr const_iterator begin() const
5931 {
5932 if (any_empty(etl::make_index_sequence<sizeof...(Ranges)>{}))
5933 {
5934 return end();
5935 }
5936 return make_begin(etl::make_index_sequence<sizeof...(Ranges)>{});
5937 }
5938
5939 constexpr const_iterator end() const
5940 {
5941 return make_end(etl::make_index_sequence<sizeof...(Ranges)>{});
5942 }
5943
5944 constexpr size_t size() const
5945 {
5946 return get_product_size(etl::make_index_sequence<sizeof...(Ranges)>{});
5947 }
5948
5949 private:
5950
5951 template <size_t... Is>
5952 constexpr const_iterator make_begin(etl::index_sequence<Is...>) const
5953 {
5954 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...),
5955 typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...),
5956 typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...), false);
5957 }
5958
5959 template <size_t... Is>
5960 constexpr const_iterator make_end(etl::index_sequence<Is...>) const
5961 {
5962 return const_iterator(typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...),
5963 typename const_iterator::iterators_type(ETL_OR_STD::begin(etl::get<Is>(_r))...),
5964 typename const_iterator::iterators_type(ETL_OR_STD::end(etl::get<Is>(_r))...), true);
5965 }
5966
5967 template <size_t... Is>
5968 constexpr bool any_empty(etl::index_sequence<Is...>) const
5969 {
5970 return ((ETL_OR_STD::begin(etl::get<Is>(_r)) == ETL_OR_STD::end(etl::get<Is>(_r))) || ...);
5971 }
5972
5973 template <size_t... Is>
5974 constexpr size_t get_product_size(etl::index_sequence<Is...>) const
5975 {
5976 size_t sizes[] = {static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(etl::get<Is>(_r)), ETL_OR_STD::cend(etl::get<Is>(_r))))...};
5977 size_t product = 1;
5978 for (size_t i = 0; i < sizeof...(Ranges); ++i)
5979 {
5980 product *= sizes[i];
5981 }
5982 return product;
5983 }
5984
5985 mutable etl::tuple<Ranges...> _r;
5986 };
5987
5988 template <class... Ranges>
5989 cartesian_product_view(Ranges&&...) -> cartesian_product_view<views::all_t<Ranges>...>;
5990
5991 namespace views
5992 {
5993 namespace private_views
5994 {
5995 struct cartesian_product
5996 {
5997 template <class... Ranges>
5998 constexpr auto operator()(Ranges&&... r) const
5999 {
6000 return cartesian_product_view(views::all(etl::forward<Ranges>(r))...);
6001 }
6002 };
6003 } // namespace private_views
6004
6005 inline constexpr private_views::cartesian_product cartesian_product;
6006 } // namespace views
6007
6008 //*************************************************************************
6013 //*************************************************************************
6014 template <class Range>
6015 class to_input_iterator
6016 {
6017 public:
6018
6019 using trait = typename etl::ranges::private_ranges::iterator_trait<Range>;
6020
6021 using iterator = typename trait::iterator;
6022 using const_iterator = typename trait::const_iterator;
6023 using value_type = typename trait::value_type;
6024 using difference_type = typename trait::difference_type;
6025 using pointer = typename trait::pointer;
6026 using reference = typename trait::reference;
6027
6028 using iterator_category = ETL_OR_STD::input_iterator_tag;
6029
6030 to_input_iterator() = default;
6031
6032 to_input_iterator(iterator it)
6033 : _it(it)
6034 {
6035 }
6036
6037 to_input_iterator(const to_input_iterator& other) = default;
6038
6039 to_input_iterator& operator=(const to_input_iterator& other) = default;
6040
6041 to_input_iterator& operator++()
6042 {
6043 ++_it;
6044 return *this;
6045 }
6046
6047 to_input_iterator operator++(int)
6048 {
6049 to_input_iterator tmp = *this;
6050 ++(*this);
6051 return tmp;
6052 }
6053
6054 decltype(auto) operator*() const
6055 {
6056 return *_it;
6057 }
6058
6059 pointer operator->() const
6060 {
6061 return &(*_it);
6062 }
6063
6064 bool operator==(const to_input_iterator& other) const
6065 {
6066 return _it == other._it;
6067 }
6068
6069 bool operator!=(const to_input_iterator& other) const
6070 {
6071 return !(*this == other);
6072 }
6073
6074 private:
6075
6076 mutable iterator _it;
6077 };
6078
6079 //*************************************************************************
6085 //*************************************************************************
6086 template <class Range>
6087 class to_input_view : public etl::ranges::view_interface<to_input_view<Range>>
6088 {
6089 public:
6090
6091 using iterator = to_input_iterator<Range>;
6092 using const_iterator = iterator;
6093
6094 to_input_view(const to_input_view& other) = default;
6095
6096 to_input_view(Range&& r)
6097 : _r{etl::move(r)}
6098 {
6099 }
6100
6101 constexpr Range& base() const
6102 {
6103 return _r;
6104 }
6105
6106 constexpr iterator begin() const
6107 {
6108 return iterator(ETL_OR_STD::begin(_r));
6109 }
6110
6111 constexpr iterator end() const
6112 {
6113 return iterator(ETL_OR_STD::end(_r));
6114 }
6115
6116 constexpr size_t size() const
6117 {
6118 return static_cast<size_t>(etl::distance(ETL_OR_STD::cbegin(_r), ETL_OR_STD::cend(_r)));
6119 }
6120
6121 private:
6122
6123 mutable Range _r;
6124 };
6125
6126 template <class Range>
6127 to_input_view(Range&&) -> to_input_view<views::all_t<Range>>;
6128
6129 struct to_input_range_adapter_closure : public range_adapter_closure<to_input_range_adapter_closure>
6130 {
6131 template <typename Range>
6132 using target_view_type = to_input_view<Range>;
6133
6134 to_input_range_adapter_closure() = default;
6135
6136 template <typename Range>
6137 constexpr auto operator()(Range&& r)
6138 {
6139 return to_input_view(views::all(etl::forward<Range>(r)));
6140 }
6141 };
6142
6143 namespace views
6144 {
6145 namespace private_views
6146 {
6147 struct to_input : public range_adapter_closure_base
6148 {
6149 template <class Range>
6150 constexpr auto operator()(Range&& r) const
6151 {
6152 return to_input_view(views::all(etl::forward<Range>(r)));
6153 }
6154
6155 constexpr auto operator()() const
6156 {
6157 return ranges::to_input_range_adapter_closure();
6158 }
6159 };
6160 } // namespace private_views
6161
6162 inline constexpr private_views::to_input to_input;
6163 } // namespace views
6164
6165 //*************************************************************************
6172 //*************************************************************************
6173 template <class R>
6174 struct elements_of
6175 {
6176 R range;
6177 };
6178
6179 template <class R>
6180 elements_of(R&&) -> elements_of<R>;
6181
6182 namespace private_ranges
6183 {
6184 template <class C>
6185 struct to_range_adapter_closure : public range_adapter_closure<to_range_adapter_closure<C>>
6186 {
6187 template <class Range = void>
6188 using target_view_type = C;
6189
6190 to_range_adapter_closure() = default;
6191
6192 template <class Range>
6193 C operator()(const Range& r) const
6194 {
6195 using result_type = C;
6196
6197 result_type result;
6198
6199 for (auto i : r)
6200 {
6201 result.push_back(i);
6202 }
6203
6204 return result;
6205 }
6206
6207 template <class Range>
6208 C operator()(Range&& r)
6209 {
6210 using result_type = C;
6211
6212 result_type result;
6213
6214 for (auto&& i : r)
6215 {
6216 result.emplace_back(etl::move(i));
6217 }
6218
6219 return result;
6220 }
6221 };
6222 } // namespace private_ranges
6223
6224 template <class C>
6225 private_ranges::to_range_adapter_closure<C> to()
6226 {
6227 return private_ranges::to_range_adapter_closure<C>();
6228 }
6229
6230 } // namespace ranges
6231
6232 namespace views = ranges::views;
6233} // namespace etl
6234
6235#endif
6236
6237#endif
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_CONSTEXPR14 void iota(TIterator first, TIterator last, T value)
Definition numeric.h:58
Definition absolute.h:40
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
TContainer::const_iterator cbegin(const TContainer &container)
Definition iterator.h:1156
etl::byte operator|(etl::byte lhs, etl::byte rhs)
Or.
Definition byte.h:250
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
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
T & get(array< T, Size > &a)
Definition array.h:1158
TContainer::const_iterator cend(const TContainer &container)
Definition iterator.h:1186
TContainer::iterator begin(TContainer &container)
Definition iterator.h:1136
etl::add_const< T >::type & as_const(T &t)
as_const
Definition utility.h:540
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937