/src/cppitertools/cppitertools/cycle.hpp
Line | Count | Source |
1 | | #ifndef ITER_CYCLE_H_ |
2 | | #define ITER_CYCLE_H_ |
3 | | |
4 | | #include "internal/iterator_wrapper.hpp" |
5 | | #include "internal/iterbase.hpp" |
6 | | |
7 | | #include <initializer_list> |
8 | | #include <iterator> |
9 | | #include <utility> |
10 | | |
11 | | namespace iter { |
12 | | namespace impl { |
13 | | template <typename Container> |
14 | | class Cycler; |
15 | | |
16 | | using CycleFn = IterToolFn<Cycler>; |
17 | | } |
18 | | inline constexpr impl::CycleFn cycle{}; |
19 | | } |
20 | | |
21 | | template <typename Container> |
22 | | class iter::impl::Cycler { |
23 | | private: |
24 | | friend CycleFn; |
25 | | |
26 | | Container container_; |
27 | | |
28 | | Cycler(Container&& container) |
29 | 593 | : container_(std::forward<Container>(container)) {} |
30 | | |
31 | | public: |
32 | | Cycler(Cycler&&) = default; |
33 | | template <typename ContainerT> |
34 | | class Iterator { |
35 | | private: |
36 | | template <typename> |
37 | | friend class Iterator; |
38 | | IteratorWrapper<ContainerT> sub_iter_; |
39 | | IteratorWrapper<ContainerT> sub_begin_; |
40 | | IteratorWrapper<ContainerT> sub_end_; |
41 | | |
42 | | public: |
43 | | using iterator_category = std::input_iterator_tag; |
44 | | using value_type = iterator_traits_deref<ContainerT>; |
45 | | using difference_type = std::ptrdiff_t; |
46 | | using pointer = value_type*; |
47 | | using reference = value_type&; |
48 | | |
49 | | Iterator(IteratorWrapper<ContainerT>&& sub_iter, |
50 | | IteratorWrapper<ContainerT>&& sub_end) |
51 | 1.18k | : sub_iter_{sub_iter}, |
52 | 1.18k | sub_begin_{sub_iter}, |
53 | 1.18k | sub_end_{std::move(sub_end)} {} |
54 | | |
55 | 890k | iterator_deref<ContainerT> operator*() { |
56 | 890k | return *sub_iter_; |
57 | 890k | } |
58 | | |
59 | | iterator_arrow<ContainerT> operator->() { |
60 | | return apply_arrow(sub_iter_); |
61 | | } |
62 | | |
63 | 889k | Iterator& operator++() { |
64 | 889k | ++sub_iter_; |
65 | | // reset to beginning upon reaching the sub_end_ |
66 | 889k | if (!(sub_iter_ != sub_end_)) { |
67 | 265k | sub_iter_ = sub_begin_; |
68 | 265k | } |
69 | 889k | return *this; |
70 | 889k | } |
71 | | |
72 | | Iterator operator++(int) { |
73 | | auto ret = *this; |
74 | | ++*this; |
75 | | return ret; |
76 | | } |
77 | | |
78 | | template <typename T> |
79 | 890k | bool operator!=(const Iterator<T>& other) const { |
80 | 890k | return sub_iter_ != other.sub_iter_; |
81 | 890k | } |
82 | | |
83 | | template <typename T> |
84 | | bool operator==(const Iterator<T>& other) const { |
85 | | return !(*this != other); |
86 | | } |
87 | | }; |
88 | | |
89 | 593 | Iterator<Container> begin() { |
90 | 593 | return {get_begin(container_), get_end(container_)}; |
91 | 593 | } |
92 | | |
93 | 593 | Iterator<Container> end() { |
94 | 593 | return {get_end(container_), get_end(container_)}; |
95 | 593 | } |
96 | | |
97 | | Iterator<AsConst<Container>> begin() const { |
98 | | return {get_begin(std::as_const(container_)), |
99 | | get_end(std::as_const(container_))}; |
100 | | } |
101 | | |
102 | | Iterator<AsConst<Container>> end() const { |
103 | | return {get_end(std::as_const(container_)), |
104 | | get_end(std::as_const(container_))}; |
105 | | } |
106 | | }; |
107 | | |
108 | | #endif |