qxLib
base_iterator.h
Go to the documentation of this file.
1 /**
2 
3  @file base_iterator.h
4  @author Khrapov
5  @date 2.12.2023
6  @copyright © Nick Khrapov, 2023. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <qx/meta/concepts.h>
12 
13 #include <iterator>
14 #include <ranges>
15 
16 namespace qx
17 {
18 
19 /**
20 
21  @class base_iterator
22  @brief Base contiguous iterator with a container pointer and an index
23  @tparam container_t - container satisfying std::ranges::contiguous_range concept
24  @author Khrapov
25  @date 2.12.2023
26 
27 **/
28 template<class container_t>
29 /* requires std::ranges::contiguous_range<container_t> */
31 {
32 public:
33  template<class container_t_, class derived_t_>
34  friend class base_forward_iterator;
35 
36  template<class container_t_, class derived_t_>
37  friend class base_reverse_iterator;
38 
39  using difference_type = typename container_t::difference_type;
40  using size_type = typename container_t::size_type;
41  using value_type = typename container_t::value_type;
42  using pointer = typename container_t::pointer;
43  using const_pointer = typename container_t::const_pointer;
44  using reference = typename container_t::reference;
45  using const_reference = typename container_t::const_reference;
46 
47  using iterator_category = std::contiguous_iterator_tag;
48  using iterator_concept = std::contiguous_iterator_tag;
49 
50 public:
51  constexpr base_iterator() noexcept = default;
52  constexpr base_iterator(container_t* pContainer, size_type nIndex) noexcept
53  : m_nIndex(nIndex)
54  , m_pContainer(pContainer)
55  {
56  }
57  constexpr operator void*() noexcept
58  {
59  return &(*m_pContainer).at(m_nIndex);
60  }
61 
62 protected:
63  void shift(difference_type nShift) noexcept
64  {
65  m_nIndex += nShift;
66  }
67  auto&& get(difference_type nShift = 0) const noexcept
68  {
69  return (*m_pContainer).at(m_nIndex + nShift);
70  }
71  size_type get_index() const noexcept
72  {
73  return m_nIndex;
74  }
75 
76 private:
77  size_type m_nIndex = 0u;
78  container_t* m_pContainer = nullptr;
79 };
80 
81 /**
82 
83  @class base_forward_iterator
84  @brief Basic contiguous forward iterator, meaning that incrementing an iterator will lead it moving forward
85  @tparam container_t - container satisfying std::ranges::contiguous_range concept
86  @tparam derived_t - derived iterator type
87  @author Khrapov
88  @date 2.12.2023
89 
90 **/
91 template<class container_t, class derived_t>
92 class base_forward_iterator : public base_iterator<container_t>
93 {
95  using decayed_derived_type = std::decay_t<derived_t>;
96 
97 public:
98  using super_type::super_type;
99 
100  template<class iterator_t>
101  requires derived_from_template_c<iterator_t, base_iterator>
102  constexpr typename super_type::difference_type operator-(const iterator_t& r) const noexcept
103  {
104  return static_cast<typename super_type::difference_type>(super_type::get_index() - r.get_index());
105  }
106  constexpr bool operator<(const base_forward_iterator& r) const noexcept
107  {
108  return super_type::get_index() < r.get_index();
109  }
110  constexpr bool operator<=(const base_forward_iterator& r) const noexcept
111  {
112  return super_type::get_index() <= r.get_index();
113  }
114  constexpr bool operator>(const base_forward_iterator& r) const noexcept
115  {
116  return super_type::get_index() > r.get_index();
117  }
118  constexpr bool operator>=(const base_forward_iterator& r) const noexcept
119  {
120  return super_type::get_index() >= r.get_index();
121  }
122  constexpr bool operator!=(const base_forward_iterator& r) const noexcept
123  {
124  return super_type::get_index() != r.get_index();
125  }
126  constexpr bool operator==(const base_forward_iterator& r) const noexcept
127  {
128  return super_type::get_index() == r.get_index();
129  }
130  constexpr decayed_derived_type& operator++() noexcept
131  {
132  super_type::shift(1);
133  return static_cast<decayed_derived_type&>(*this);
134  }
135  constexpr decayed_derived_type& operator--() noexcept
136  {
137  super_type::shift(-1);
138  return static_cast<decayed_derived_type&>(*this);
139  }
140  [[nodiscard]] constexpr decayed_derived_type operator++(int) noexcept
141  {
142  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
143  super_type::shift(1);
144  return r;
145  }
146  [[nodiscard]] constexpr decayed_derived_type operator--(int) noexcept
147  {
148  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
149  super_type::shift(-1);
150  return r;
151  }
152  constexpr decayed_derived_type& operator+=(typename super_type::difference_type n) noexcept
153  {
154  super_type::shift(n);
155  return static_cast<decayed_derived_type&>(*this);
156  }
157  constexpr decayed_derived_type& operator-=(typename super_type::difference_type n) noexcept
158  {
159  super_type::shift(-n);
160  return static_cast<decayed_derived_type&>(*this);
161  }
162  constexpr decayed_derived_type operator+(typename super_type::difference_type n) const noexcept
163  {
164  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
165  return r += n;
166  }
167  constexpr decayed_derived_type operator-(typename super_type::difference_type n) const noexcept
168  {
169  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
170  return r -= n;
171  }
172 };
173 
174 template<class iterator_t>
175  requires derived_from_template_c<iterator_t, base_forward_iterator>
176 constexpr iterator_t operator+(typename iterator_t::size_type n, iterator_t it) noexcept
177 {
178  return it += n;
179 }
180 
181 /**
182 
183  @class base_reverse_iterator
184  @brief Basic contiguous reverse iterator, meaning that incrementing an iterator will lead it moving backward
185  @tparam container_t - container satisfying std::ranges::contiguous_range concept
186  @tparam derived_t - derived iterator type
187  @author Khrapov
188  @date 2.12.2023
189 
190 **/
191 template<class container_t, class derived_t>
192 class base_reverse_iterator : public base_iterator<container_t>
193 {
195  using decayed_derived_type = std::decay_t<derived_t>;
196 
197 public:
198  using super_type::super_type;
199 
200  template<class iterator_t>
201  requires derived_from_template_c<iterator_t, base_iterator>
202  constexpr typename super_type::difference_type operator-(const iterator_t& r) const noexcept
203  {
204  return static_cast<typename super_type::difference_type>(r.get_index() - super_type::get_index());
205  }
206  // + 1 is necessary, as `m_nIndex = -1 (aka size_type::max)`
207  // may be used as end (past-the-last) element
208  constexpr bool operator<(const base_reverse_iterator& r) const noexcept
209  {
210  return super_type::get_index() + 1 > r.get_index() + 1;
211  }
212  constexpr bool operator<=(const base_reverse_iterator& r) const noexcept
213  {
214  return super_type::get_index() + 1 >= r.get_index() + 1;
215  }
216  constexpr bool operator>(const base_reverse_iterator& r) const noexcept
217  {
218  return super_type::get_index() + 1 < r.get_index() + 1;
219  }
220  constexpr bool operator>=(const base_reverse_iterator& r) const noexcept
221  {
222  return super_type::get_index() + 1 <= r.get_index() + 1;
223  }
224  constexpr bool operator!=(const base_reverse_iterator& r) const noexcept
225  {
226  return super_type::get_index() + 1 != r.get_index() + 1;
227  }
228  constexpr bool operator==(const base_reverse_iterator& r) const noexcept
229  {
230  return super_type::get_index() + 1 == r.get_index() + 1;
231  }
232  constexpr decayed_derived_type& operator++() noexcept
233  {
234  super_type::shift(-1);
235  return static_cast<decayed_derived_type&>(*this);
236  }
237  constexpr decayed_derived_type& operator--() noexcept
238  {
239  super_type::shift(1);
240  return static_cast<decayed_derived_type&>(*this);
241  }
242  [[nodiscard]] constexpr decayed_derived_type operator++(int) noexcept
243  {
244  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
245  super_type::shift(-1);
246  return r;
247  }
248  [[nodiscard]] constexpr decayed_derived_type operator--(int) noexcept
249  {
250  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
251  super_type::shift(1);
252  return r;
253  }
254  constexpr decayed_derived_type& operator+=(typename super_type::difference_type n) noexcept
255  {
256  super_type::shift(-n);
257  return static_cast<decayed_derived_type&>(*this);
258  }
259  constexpr decayed_derived_type& operator-=(typename super_type::difference_type n) noexcept
260  {
261  super_type::shift(n);
262  return static_cast<decayed_derived_type&>(*this);
263  }
264  constexpr decayed_derived_type operator+(typename super_type::difference_type n) const noexcept
265  {
266  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
267  return r += n;
268  }
269  constexpr decayed_derived_type operator-(typename super_type::difference_type n) const noexcept
270  {
271  decayed_derived_type r(static_cast<const decayed_derived_type&>(*this));
272  return r -= n;
273  }
274 };
275 
276 template<class iterator_t>
277  requires derived_from_template_c<iterator_t, base_reverse_iterator>
278 constexpr iterator_t operator+(typename iterator_t::size_type n, iterator_t it) noexcept
279 {
280  return it += n;
281 }
282 
283 } // namespace qx
Basic contiguous forward iterator, meaning that incrementing an iterator will lead it moving forward.
Definition: base_iterator.h:93
Base contiguous iterator with a container pointer and an index.
Definition: base_iterator.h:31
Basic contiguous reverse iterator, meaning that incrementing an iterator will lead it moving backward...