SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
inherited_iterator_base.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 
21 
22 namespace seqan3::detail
23 {
24 
48 template <typename derived_t, std::input_or_output_iterator base_t>
49 class inherited_iterator_base :
50  public std::conditional_t<std::is_pointer_v<base_t> || !std::semiregular<base_t>, empty_type, base_t>,
51  public maybe_inherited_iterator_category<base_t>
52 {
53 private:
55  static constexpr bool wrap_base = std::is_pointer_v<base_t> || !std::semiregular<base_t>;
56 
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() noexcept(std::is_nothrow_default_constructible_v<base_t>) =
84  default;
85  constexpr inherited_iterator_base(inherited_iterator_base const & rhs) noexcept(
86  std::is_nothrow_copy_constructible_v<base_t>) = default;
87  constexpr inherited_iterator_base(inherited_iterator_base && rhs) noexcept(
88  std::is_nothrow_move_constructible_v<base_t>) = default;
89  constexpr inherited_iterator_base & operator=(inherited_iterator_base const & rhs) noexcept(
90  std::is_nothrow_copy_assignable_v<base_t>) = default;
91  constexpr inherited_iterator_base & operator=(inherited_iterator_base && rhs) noexcept(
92  std::is_nothrow_move_assignable_v<base_t>) = default;
93  ~inherited_iterator_base() noexcept(std::is_nothrow_destructible_v<base_t>) = default;
94 
96  constexpr inherited_iterator_base(base_t it) noexcept(std::is_nothrow_move_constructible_v<base_t>)
97  requires (!wrap_base)
98  : base_t{std::move(it)}
99  {}
100 
102  constexpr inherited_iterator_base(base_t it) noexcept
103  requires wrap_base
104  : member{std::move(it)}
105  {}
107 
109  constexpr base_t const & base() const & noexcept
110  {
111  return as_base();
112  }
113 
115  constexpr base_t & base() & noexcept
116  {
117  return as_base();
118  }
119 
121  constexpr base_t base() && noexcept
122  {
123  return std::move(as_base());
124  }
125 
132  constexpr bool operator==(derived_t const & rhs) const
133  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
134  requires std::equality_comparable<base_t>
135  {
136  return base() == rhs.base();
137  }
138 
140  constexpr bool operator!=(derived_t const & rhs) const
141  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
142  requires std::equality_comparable<base_t>
143  {
144  return !(*this == rhs);
145  }
146 
148  constexpr bool operator<(derived_t const & rhs) const
149  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
150  requires std::totally_ordered<base_t>
151  {
152  return base() < rhs.base();
153  }
154 
156  constexpr bool operator>(derived_t const & rhs) const
157  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
158  requires std::totally_ordered<base_t>
159  {
160  return base() > rhs.base();
161  }
162 
164  constexpr bool operator<=(derived_t const & rhs) const
165  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
166  requires std::totally_ordered<base_t>
167  {
168  return !(*this > rhs);
169  }
170 
172  constexpr bool operator>=(derived_t const & rhs) const
173  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
174  requires std::totally_ordered<base_t>
175  {
176  return !(*this < rhs);
177  }
179 
186  template <typename base_t_ = base_t>
188  constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
189  requires requires (base_t_ i) { ++i; }
190  {
191  ++as_base();
192  return *this_derived();
193  }
194 
197  template <typename base_t_ = base_t>
199  constexpr auto operator++(int) noexcept(noexcept(std::declval<base_t &>()++))
200  requires requires (base_t_ i) {
201  i++;
202  requires !std::same_as<decltype(i++), base_t_>;
203  }
204  {
205  return as_base()++;
206  }
207 
210  template <typename base_t_ = base_t>
212  constexpr derived_t
213  operator++(int) noexcept(noexcept(std::declval<base_t &>()++) && noexcept(derived_t(std::declval<base_t &>())))
214  requires requires (base_t_ i) {
215  i++;
216  {
217  i++
218  } -> std::same_as<base_t_>;
219  } && std::constructible_from<derived_t, base_t_>
220  {
221  return derived_t{as_base()++};
222  }
223 
226  template <typename base_t_ = base_t>
228  constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
229  requires requires (base_t_ i) { --i; }
230  {
231  --as_base();
232  return *this_derived();
233  }
234 
237  template <typename base_t_ = base_t>
239  constexpr derived_t
240  operator--(int) noexcept(noexcept(std::declval<base_t &>()--) && noexcept(derived_t{std::declval<base_t &>()}))
241  requires requires (base_t_ i) { i--; } && std::constructible_from<derived_t, base_t_>
242  {
243  return derived_t{as_base()--};
244  }
245 
248  template <typename base_t_ = base_t>
250  constexpr derived_t & operator+=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() += skip))
251  requires requires (base_t_ i, difference_type const n) { i += n; }
252  {
253  as_base() += skip;
254  return *this_derived();
255  }
256 
259  template <typename base_t_ = base_t>
261  constexpr derived_t operator+(difference_type const skip) const
262  noexcept(noexcept(std::declval<base_t &>() + skip) && noexcept(derived_t{std::declval<base_t &>()}))
263  requires requires (base_t_ const i, difference_type const n) { i + n; }
264  && std::constructible_from<derived_t, base_t_>
265  {
266  return derived_t{as_base() + skip};
267  }
268 
270  constexpr friend derived_t operator+(difference_type const skip,
271  derived_t const & it) noexcept(noexcept(skip + std::declval<base_t const &>()))
272  requires requires (base_t const i, difference_type const n) { n + i; }
273  && std::constructible_from<derived_t, base_t>
274  {
275  return it + skip;
276  }
277 
280  template <typename base_t_ = base_t>
282  constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() -= skip))
283  requires requires (base_t_ i, difference_type const n) { i -= n; }
284  {
285  as_base() -= skip;
286  return *this_derived();
287  }
288 
291  template <typename base_t_ = base_t>
293  constexpr derived_t operator-(difference_type const skip) const
294  noexcept(noexcept(std::declval<base_t const &>() - skip) && noexcept(derived_t(std::declval<base_t &>())))
295  requires requires (base_t_ i, difference_type const n) { i - n; } && std::constructible_from<derived_t, base_t_>
296  {
297  return derived_t{as_base() - skip};
298  }
299 
301  constexpr difference_type operator-(derived_t const & rhs) const
302  noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
303  requires std::sized_sentinel_for<base_t, base_t>
304  {
305  return as_base() - rhs.as_base();
306  }
308 
313  constexpr reference operator*() noexcept(noexcept(*std::declval<base_t &>()))
314  requires std::indirectly_readable<base_t>
315  {
316  return *as_base();
317  }
318 
320  constexpr decltype(auto) operator*() const noexcept(noexcept(*std::declval<base_t const &>()))
321  requires std::indirectly_readable<base_t>
322  {
323  return *as_base();
324  }
325 
327  constexpr pointer operator->() noexcept(noexcept(*std::declval<base_t &>()))
328  requires std::input_iterator<base_t>
329  {
330  return &as_base();
331  }
332 
334  constexpr decltype(auto) operator->() const noexcept(noexcept(*std::declval<base_t const &>()))
335  requires std::input_iterator<base_t>
336  {
337  return &as_base();
338  }
339 
342  template <typename base_t_ = base_t>
344  constexpr decltype(auto)
345  operator[](std::make_signed_t<difference_type> const n) noexcept(noexcept(std::declval<base_t &>()[0]))
346  requires requires (base_t_ i, difference_type const n) { i[n]; }
347  {
348  return as_base()[n];
349  }
350 
353  template <typename base_t_ = base_t>
355  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
356  noexcept(noexcept(std::declval<base_t const &>()[0]))
357  requires requires (base_t_ const i, difference_type const n) { i[n]; }
358  {
359  return as_base()[n];
360  }
362 
363 private:
366 
368  friend derived_t;
369 
371  constexpr base_t & as_base() & noexcept
372  {
373  if constexpr (wrap_base)
374  return member;
375  else
376  return *this;
377  }
378 
380  constexpr base_t const & as_base() const & noexcept
381  {
382  if constexpr (wrap_base)
383  return member;
384  else
385  return *this;
386  }
387 
389  constexpr derived_t * this_derived()
390  {
391  return static_cast<derived_t *>(this);
392  }
393 
395  constexpr derived_t const * this_derived() const
396  {
397  return static_cast<derived_t const *>(this);
398  }
399 };
400 
401 } // namespace seqan3::detail
Provides seqan3::detail::empty_type.
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
Provides various transformation traits for use on iterators.
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)