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 
22 namespace seqan3::detail
23 {
24 
48 template <typename derived_t, std::input_or_output_iterator base_t>
49 class 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 {
54 private:
56  static constexpr bool wrap_base = std::is_pointer_v<base_t> || !std::semiregular<base_t>;
57 public:
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 
408 private:
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