SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
random_access_iterator.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, 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 <seqan3/std/iterator>
17#include <type_traits>
18
20
21namespace seqan3::detail
22{
23
40template <typename range_type, template <typename ...> typename derived_t_template>
41class random_access_iterator_base
42{
43protected:
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>
54 requires std::is_const_v<range_type> && (!std::is_const_v<range_type2>) &&
56 std::is_same_v<derived_t_template2, derived_t_template>
58 friend class random_access_iterator_base;
59
61 using derived_t = derived_t_template <range_type>;
62
63public:
65 using difference_type = typename range_type::difference_type; // TODO should be range_ but is broken in ranges
67 using value_type = typename range_type::value_type;
70 typename range_type::const_reference,
71 typename range_type::reference>;
73 using const_reference = typename range_type::const_reference; //TODO: there is no type trait for this, yet :o
75 using pointer = value_type *;
77 using iterator_category = std::random_access_iterator_tag;
78
83 constexpr random_access_iterator_base() = default;
85 constexpr random_access_iterator_base(random_access_iterator_base const &) = default;
87 constexpr random_access_iterator_base & operator=(random_access_iterator_base const &) = default;
89 constexpr random_access_iterator_base (random_access_iterator_base &&) = default;
91 constexpr random_access_iterator_base & operator=(random_access_iterator_base &&) = default;
93 ~random_access_iterator_base() = default;
94
96 explicit constexpr random_access_iterator_base(range_type & host) noexcept : host{&host} {}
98 constexpr random_access_iterator_base(range_type & host, position_type const pos) noexcept :
99 host{&host}, pos{pos}
100 {}
101
103 template <typename range_type2>
105 requires std::is_const_v<range_type> && (!std::is_const_v<range_type2>) &&
108 constexpr random_access_iterator_base(random_access_iterator_base<range_type2, derived_t_template> const & rhs) noexcept :
109 host{rhs.host}, pos{rhs.pos}
110 {}
112
120 template <typename range_type2>
122 requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
124 constexpr bool operator==(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
125 {
126 return pos == rhs.pos;
127 }
128
130 template <typename range_type2>
132 requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
134 constexpr bool operator!=(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
135 {
136 return !(*this == rhs);
137 }
138
140 template <typename range_type2>
142 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 static_cast<bool>(pos < rhs.pos);
147 }
148
150 template <typename range_type2>
152 requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
154 constexpr bool operator>(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
155 {
156 return pos > rhs.pos;
157 }
158
160 template <typename range_type2>
162 requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
164 constexpr bool operator<=(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
165 {
166 return pos <= rhs.pos;
167 }
168
170 template <typename range_type2>
172 requires std::is_same_v<std::remove_const_t<range_type>, std::remove_const_t<range_type2>>
174 constexpr bool operator>=(random_access_iterator_base<range_type2, derived_t_template> const & rhs) const noexcept
175 {
176 return pos >= rhs.pos;
177 }
179
185 constexpr derived_t & operator++() noexcept
186 {
187 ++pos;
188 return *this_derived();
189 }
190
192 constexpr derived_t operator++(int) noexcept
193 {
194 derived_t cpy{*this_derived()};
195 ++pos;
196 return cpy;
197 }
198
200 constexpr derived_t & operator--() noexcept
201 {
202 --pos;
203 return *this_derived();
204 }
205
207 constexpr derived_t operator--(int) noexcept
208 {
209 derived_t cpy{*this_derived()};
210 --pos;
211 return cpy;
212 }
213
215 constexpr derived_t & operator+=(difference_type const skip) noexcept
216 {
217 pos += skip;
218 return *this_derived();
219 }
220
222 constexpr derived_t operator+(difference_type const skip) const noexcept
223 {
224 derived_t cpy{*this_derived()};
225 return cpy += skip;
226 }
227
229 constexpr friend derived_t operator+(difference_type const skip, derived_t const & it) noexcept
230 {
231 return it + skip;
232 }
233
235 constexpr derived_t & operator-=(difference_type const skip) noexcept
236 {
237 pos -= skip;
238 return *this_derived();
239 }
240
242 constexpr derived_t operator-(difference_type const skip) const noexcept
243 {
244 derived_t cpy{*this_derived()};
245 return cpy -= skip;
246 }
247
249 constexpr friend derived_t operator-(difference_type const skip, derived_t const & it) noexcept
250 {
251 return it - skip;
252 }
253
255 constexpr friend difference_type operator-(derived_t const & lhs, derived_t const & rhs) noexcept
256 {
257 return static_cast<difference_type>(lhs.pos - rhs.pos);
258 }
260
266 constexpr reference operator*() const noexcept(noexcept((*host)[pos]))
267 {
268 return (*host)[pos];
269 }
270
272 constexpr pointer operator->() const noexcept(noexcept((&host)[pos]))
273 {
274 return &host[pos];
275 }
276
278 constexpr reference operator[](position_type const n) const noexcept(noexcept((*host)[pos+n]))
279 {
280 return (*host)[pos + n];
281 }
283
284private:
285
287 constexpr derived_t* this_derived()
288 {
289 return static_cast<derived_t*>(this);
290 }
291
293 constexpr derived_t const * this_derived() const
294 {
295 return static_cast<derived_t const *>(this);
296 }
297};
298
307template <typename range_type>
308class random_access_iterator :
309 public random_access_iterator_base<range_type, random_access_iterator>
310{
311private:
313 using base = random_access_iterator_base<range_type, random_access_iterator>;
315 using typename base::position_type;
316
317public:
322 using typename base::difference_type;
323 using typename base::value_type;
324 using typename base::reference;
325 using typename base::const_reference;
326 using typename base::pointer;
327 using typename base::iterator_category;
329
331 using base::base;
332};
333
334} // namespace seqan3::detail
T is_same_v
The <iterator> header from C++20's standard library.
T operator!=(T... args)
Provides platform and dependency checks.