SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
inherited_iterator_base.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
21
22namespace seqan3::detail
23{
24
48template <typename derived_t, std::input_or_output_iterator base_t>
49class inherited_iterator_base : public std::conditional_t<std::is_pointer_v<base_t> || !std::semiregular<base_t>,
50 empty_type,
51 base_t>,
52 public maybe_inherited_iterator_category<base_t>
53{
54private:
56 static constexpr bool wrap_base = std::is_pointer_v<base_t> || !std::semiregular<base_t>;
57public:
64 using difference_type = std::iter_difference_t<base_t>;
66 using value_type = std::iter_value_t<base_t>;
68 using reference = std::iter_reference_t<base_t>;
70 using pointer = detail::iter_pointer_t<base_t>;
71#if SEQAN3_DOXYGEN_ONLY(1)0
73 using iterator_category = maybe_present;
74#endif // SEQAN3_DOXYGEN_ONLY(1)0
76 using iterator_concept = detail::iterator_concept_tag_t<base_t>;
78
83 constexpr inherited_iterator_base()
84 noexcept(std::is_nothrow_default_constructible_v<base_t>) = default;
85 constexpr inherited_iterator_base(inherited_iterator_base const & rhs)
86 noexcept(std::is_nothrow_copy_constructible_v<base_t>) = default;
87 constexpr inherited_iterator_base(inherited_iterator_base && rhs)
88 noexcept(std::is_nothrow_move_constructible_v<base_t>) = default;
89 constexpr inherited_iterator_base & operator=(inherited_iterator_base const & rhs)
90 noexcept(std::is_nothrow_copy_assignable_v<base_t>) = default;
91 constexpr inherited_iterator_base & operator=(inherited_iterator_base && rhs)
92 noexcept(std::is_nothrow_move_assignable_v<base_t>) = default;
93 ~inherited_iterator_base()
94 noexcept(std::is_nothrow_destructible_v<base_t>) = default;
95
97 constexpr inherited_iterator_base(base_t it) noexcept(std::is_nothrow_move_constructible_v<base_t>)
99 requires (!wrap_base)
101 : base_t{std::move(it)}
102 {}
103
105 constexpr inherited_iterator_base(base_t it) noexcept
107 requires wrap_base
109 : member{std::move(it)}
110 {}
112
114 constexpr base_t const & base() const & noexcept
115 {
116 return as_base();
117 }
118
120 constexpr base_t & base() & noexcept
121 {
122 return as_base();
123 }
124
126 constexpr base_t base() && noexcept
127 {
128 return std::move(as_base());
129 }
130
137 constexpr bool operator==(derived_t const & rhs) const
138 noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
140 requires std::equality_comparable<base_t>
142 {
143 return base() == rhs.base();
144 }
145
147 constexpr bool operator!=(derived_t const & rhs) const
148 noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
150 requires std::equality_comparable<base_t>
152 {
153 return !(*this == rhs);
154 }
155
157 constexpr bool operator<(derived_t const & rhs) const
158 noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
160 requires std::totally_ordered<base_t>
162 {
163 return base() < rhs.base();
164 }
165
167 constexpr bool operator>(derived_t const & rhs) const
168 noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
170 requires std::totally_ordered<base_t>
172 {
173 return base() > rhs.base();
174 }
175
177 constexpr bool operator<=(derived_t const & rhs) const
178 noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
180 requires std::totally_ordered<base_t>
182 {
183 return !(*this > rhs);
184 }
185
187 constexpr bool operator>=(derived_t const & rhs) const
188 noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
190 requires std::totally_ordered<base_t>
192 {
193 return !(*this < rhs);
194 }
196
203 template <typename base_t_ = base_t>
205 constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
207 requires requires (base_t_ i) { ++i; }
209 {
210 ++as_base();
211 return *this_derived();
212 }
213
216 template <typename base_t_ = base_t>
218 constexpr auto operator++(int) noexcept(noexcept(std::declval<base_t &>()++))
220 requires requires (base_t_ i) { i++; requires !std::same_as<decltype(i++), base_t_>; }
222 {
223 return as_base()++;
224 }
225
228 template <typename base_t_ = base_t>
230 constexpr derived_t operator++(int) noexcept(noexcept(std::declval<base_t &>()++) &&
231 noexcept(derived_t(std::declval<base_t &>())))
233 requires requires (base_t_ i) { i++; SEQAN3_RETURN_TYPE_CONSTRAINT(i++, std::same_as, base_t_); } &&
234 std::constructible_from<derived_t, base_t_>
236 {
237 return derived_t{as_base()++};
238 }
239
242 template <typename base_t_ = base_t>
244 constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
246 requires requires (base_t_ i) { --i; }
248 {
249 --as_base();
250 return *this_derived();
251 }
252
255 template <typename base_t_ = base_t>
257 constexpr derived_t operator--(int) noexcept(noexcept(std::declval<base_t &>()--) &&
258 noexcept(derived_t{std::declval<base_t &>()}))
260 requires requires (base_t_ i) { i--; } && std::constructible_from<derived_t, base_t_>
262 {
263 return derived_t{as_base()--};
264 }
265
268 template <typename base_t_ = base_t>
270 constexpr derived_t & operator+=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() += skip))
272 requires requires (base_t_ i, difference_type const n) { i += n; }
274 {
275 as_base() += skip;
276 return *this_derived();
277 }
278
281 template <typename base_t_ = base_t>
283 constexpr derived_t operator+(difference_type const skip) const
284 noexcept(noexcept(std::declval<base_t &>() + skip) && noexcept(derived_t{std::declval<base_t &>()}))
286 requires requires (base_t_ const i, difference_type const n) { i + n; } &&
287 std::constructible_from<derived_t, base_t_>
289 {
290 return derived_t{as_base() + skip};
291 }
292
294 constexpr friend derived_t operator+(difference_type const skip, derived_t const & it)
295 noexcept(noexcept(skip + std::declval<base_t const &>()))
297 requires requires (base_t const i, difference_type const n) { n + i; } &&
298 std::constructible_from<derived_t, base_t>
300 {
301 return it + skip;
302 }
303
306 template <typename base_t_ = base_t>
308 constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() -= skip))
310 requires requires (base_t_ i, difference_type const n) { i -= n; }
312 {
313 as_base() -= skip;
314 return *this_derived();
315 }
316
319 template <typename base_t_ = base_t>
321 constexpr derived_t operator-(difference_type const skip) const
322 noexcept(noexcept(std::declval<base_t const &>() - skip) && noexcept(derived_t(std::declval<base_t &>())))
324 requires requires (base_t_ i, difference_type const n) { i - n; } &&
325 std::constructible_from<derived_t, base_t_>
327 {
328 return derived_t{as_base() - skip};
329 }
330
332 constexpr difference_type operator-(derived_t const & rhs) const
333 noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
335 requires std::sized_sentinel_for<base_t, base_t>
337 {
338 return as_base() - rhs.as_base();
339 }
341
346 constexpr reference operator*() noexcept(noexcept(*std::declval<base_t &>()))
348 requires std::indirectly_readable<base_t>
350 {
351 return *as_base();
352 }
353
355 constexpr decltype(auto) operator*() const noexcept(noexcept(*std::declval<base_t const &>()))
357 requires std::indirectly_readable<base_t>
359 {
360 return *as_base();
361 }
362
364 constexpr pointer operator->() noexcept(noexcept(*std::declval<base_t &>()))
366 requires std::input_iterator<base_t>
368 {
369 return &as_base();
370 }
371
373 constexpr decltype(auto) operator->() const noexcept(noexcept(*std::declval<base_t const &>()))
375 requires std::input_iterator<base_t>
377 {
378 return &as_base();
379 }
380
383 template <typename base_t_ = base_t>
385 constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n)
386 noexcept(noexcept(std::declval<base_t &>()[0]))
388 requires requires (base_t_ i, difference_type const n) { i[n]; }
390 {
391 return as_base()[n];
392 }
393
396 template <typename base_t_ = base_t>
398 constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
399 noexcept(noexcept(std::declval<base_t const &>()[0]))
401 requires requires (base_t_ const i, difference_type const n) { i[n]; }
403 {
404 return as_base()[n];
405 }
407
408private:
411
413 friend derived_t;
414
416 constexpr base_t & as_base() & noexcept
417 {
418 if constexpr (wrap_base)
419 return member;
420 else
421 return *this;
422 }
423
425 constexpr base_t const & as_base() const & noexcept
426 {
427 if constexpr (wrap_base)
428 return member;
429 else
430 return *this;
431 }
432
434 constexpr derived_t * this_derived()
435 {
436 return static_cast<derived_t*>(this);
437 }
438
440 constexpr derived_t const * this_derived() const
441 {
442 return static_cast<derived_t const *>(this);
443 }
444};
445
446} // namespace seqan3::detail
Provides seqan3::detail::empty_type.
Provides various transformation traits for use on iterators.
The <iterator> header from C++20's standard library.
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
#define SEQAN3_RETURN_TYPE_CONSTRAINT(expression, concept_name,...)
Same as writing {expression} -> concept_name<type1[, ...]> in a concept definition.
Definition: platform.hpp:57