SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
random_access_iterator.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <cassert>
16 #include <iterator>
17 #include <type_traits>
18 
19 #include <seqan3/core/platform.hpp>
20 
21 namespace seqan3::detail
22 {
23 
40 template <typename range_type, template <typename...> typename derived_t_template, typename... args_t>
41 class random_access_iterator_base
42 {
43 protected:
45  typename std::add_pointer_t<range_type> host{nullptr};
49  position_type pos{static_cast<position_type>(0)};
50 
52  template <typename range_type2, template <typename...> typename derived_t_template2, typename... args2_t>
53  requires std::is_const_v<range_type>
54  && (!std::is_const_v<range_type2>) && std::is_same_v<std::remove_const_t<range_type>, range_type2>
55  && std::is_same_v<derived_t_template2<args2_t...>, derived_t_template<args_t...>>
56  friend class random_access_iterator_base;
57 
59  using derived_t = derived_t_template<range_type>;
60 
61 public:
63  using difference_type = typename range_type::difference_type; // TODO should be range_ but is broken in ranges
65  using value_type = typename range_type::value_type;
68  typename range_type::const_reference,
69  typename range_type::reference>;
71  using const_reference = typename range_type::const_reference; //TODO: there is no type trait for this, yet :o
73  using pointer = value_type *;
75  using iterator_category = std::random_access_iterator_tag;
76 
81  constexpr random_access_iterator_base() = default;
83  constexpr random_access_iterator_base(random_access_iterator_base const &) = default;
85  constexpr random_access_iterator_base & operator=(random_access_iterator_base const &) = default;
87  constexpr random_access_iterator_base(random_access_iterator_base &&) = default;
89  constexpr random_access_iterator_base & operator=(random_access_iterator_base &&) = default;
91  ~random_access_iterator_base() = default;
92 
94  explicit constexpr random_access_iterator_base(range_type & host) noexcept : host{&host}
95  {}
97  constexpr random_access_iterator_base(range_type & host, position_type const pos) noexcept : host{&host}, pos{pos}
98  {}
99 
101  template <typename range_type2>
102  requires std::is_const_v<range_type>
103  && (!std::is_const_v<range_type2>) && std::is_same_v<std::remove_const_t<range_type>, range_type2>
104  constexpr random_access_iterator_base(
105  random_access_iterator_base<range_type2, derived_t_template> const & rhs) noexcept :
106  host{rhs.host},
107  pos{rhs.pos}
108  {}
110 
118  template <typename range_type2>
119  requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
120  constexpr bool operator==(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
121  {
122  return pos == rhs.pos;
123  }
124 
126  template <typename range_type2>
127  requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
128  constexpr bool operator!=(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
129  {
130  return !(*this == rhs);
131  }
132 
134  template <typename range_type2>
135  requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
136  constexpr bool operator<(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
137  {
138  return static_cast<bool>(pos < rhs.pos);
139  }
140 
142  template <typename range_type2>
143  requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
144  constexpr bool operator>(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
145  {
146  return pos > rhs.pos;
147  }
148 
150  template <typename range_type2>
151  requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
152  constexpr bool operator<=(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
153  {
154  return pos <= rhs.pos;
155  }
156 
158  template <typename range_type2>
159  requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
160  constexpr bool operator>=(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
161  {
162  return pos >= rhs.pos;
163  }
165 
171  constexpr derived_t & operator++() noexcept
172  {
173  ++pos;
174  return *this_derived();
175  }
176 
178  constexpr derived_t operator++(int) noexcept
179  {
180  derived_t cpy{*this_derived()};
181  ++pos;
182  return cpy;
183  }
184 
186  constexpr derived_t & operator--() noexcept
187  {
188  --pos;
189  return *this_derived();
190  }
191 
193  constexpr derived_t operator--(int) noexcept
194  {
195  derived_t cpy{*this_derived()};
196  --pos;
197  return cpy;
198  }
199 
201  constexpr derived_t & operator+=(difference_type const skip) noexcept
202  {
203  pos += skip;
204  return *this_derived();
205  }
206 
208  constexpr derived_t operator+(difference_type const skip) const noexcept
209  {
210  derived_t cpy{*this_derived()};
211  return cpy += skip;
212  }
213 
215  constexpr friend derived_t operator+(difference_type const skip, derived_t const & it) noexcept
216  {
217  return it + skip;
218  }
219 
221  constexpr derived_t & operator-=(difference_type const skip) noexcept
222  {
223  pos -= skip;
224  return *this_derived();
225  }
226 
228  constexpr derived_t operator-(difference_type const skip) const noexcept
229  {
230  derived_t cpy{*this_derived()};
231  return cpy -= skip;
232  }
233 
235  constexpr friend derived_t operator-(difference_type const skip, derived_t const & it) noexcept
236  {
237  return it - skip;
238  }
239 
241  constexpr friend difference_type operator-(derived_t const & lhs, derived_t const & rhs) noexcept
242  {
243  return static_cast<difference_type>(lhs.pos - rhs.pos);
244  }
246 
252  constexpr reference operator*() const noexcept(noexcept((*host)[pos]))
253  {
254  return (*host)[pos];
255  }
256 
258  constexpr pointer operator->() const noexcept(noexcept((&host)[pos]))
259  {
260  return &host[pos];
261  }
262 
264  constexpr reference operator[](position_type const n) const noexcept(noexcept((*host)[pos + n]))
265  {
266  return (*host)[pos + n];
267  }
269 
270 private:
272  constexpr derived_t * this_derived()
273  {
274  return static_cast<derived_t *>(this);
275  }
276 
278  constexpr derived_t const * this_derived() const
279  {
280  return static_cast<derived_t const *>(this);
281  }
282 };
283 
292 template <typename range_type>
293 class random_access_iterator : public random_access_iterator_base<range_type, random_access_iterator>
294 {
295 private:
297  using base = random_access_iterator_base<range_type, random_access_iterator>;
299  using typename base::position_type;
300 
301 public:
306  using typename base::const_reference;
307  using typename base::difference_type;
308  using typename base::iterator_category;
309  using typename base::pointer;
310  using typename base::reference;
311  using typename base::value_type;
313 
315  using base::base;
316 };
317 
318 } // namespace seqan3::detail
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
T is_same_v
T operator!=(T... args)
Provides platform and dependency checks.