SeqAn3  3.0.3
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 base() const &
116  requires std::copyable<base_t>
118  {
119  return as_base();
120  }
121 
123  constexpr base_t base() &&
124  {
125  return std::move(as_base());
126  }
127 
134  constexpr bool operator==(derived_t const & rhs) const
135  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
137  requires std::equality_comparable<base_t>
139  {
140  return base() == rhs.base();
141  }
142 
144  constexpr bool operator!=(derived_t const & rhs) const
145  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
147  requires std::equality_comparable<base_t>
149  {
150  return !(*this == rhs);
151  }
152 
154  constexpr bool operator<(derived_t const & rhs) const
155  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
157  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 &>()))
167  requires std::totally_ordered<base_t>
169  {
170  return base() > rhs.base();
171  }
172 
174  constexpr bool operator<=(derived_t const & rhs) const
175  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
177  requires std::totally_ordered<base_t>
179  {
180  return !(*this > rhs);
181  }
182 
184  constexpr bool operator>=(derived_t const & rhs) const
185  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
187  requires std::totally_ordered<base_t>
189  {
190  return !(*this < rhs);
191  }
193 
200  template <typename base_t_ = base_t>
202  constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
204  requires requires (base_t_ i) { ++i; }
206  {
207  ++as_base();
208  return *this_derived();
209  }
210 
213  template <typename base_t_ = base_t>
215  constexpr auto operator++(int) noexcept(noexcept(std::declval<base_t &>()++))
217  requires requires (base_t_ i) { i++; requires !std::same_as<decltype(i++), base_t_>; }
219  {
220  return as_base()++;
221  }
222 
225  template <typename base_t_ = base_t>
227  constexpr derived_t operator++(int) noexcept(noexcept(std::declval<base_t &>()++) &&
228  noexcept(derived_t(std::declval<base_t &>())))
230  requires requires (base_t_ i) { i++; SEQAN3_RETURN_TYPE_CONSTRAINT(i++, std::same_as, base_t_); } &&
231  std::constructible_from<derived_t, base_t_>
233  {
234  return derived_t{as_base()++};
235  }
236 
239  template <typename base_t_ = base_t>
241  constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
243  requires requires (base_t_ i) { --i; }
245  {
246  --as_base();
247  return *this_derived();
248  }
249 
252  template <typename base_t_ = base_t>
254  constexpr derived_t operator--(int) noexcept(noexcept(std::declval<base_t &>()--) &&
255  noexcept(derived_t{std::declval<base_t &>()}))
257  requires requires (base_t_ i) { i--; } && std::constructible_from<derived_t, base_t_>
259  {
260  return derived_t{as_base()--};
261  }
262 
265  template <typename base_t_ = base_t>
267  constexpr derived_t & operator+=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() += skip))
269  requires requires (base_t_ i, difference_type const n) { i += n; }
271  {
272  as_base() += skip;
273  return *this_derived();
274  }
275 
278  template <typename base_t_ = base_t>
280  constexpr derived_t operator+(difference_type const skip) const
281  noexcept(noexcept(std::declval<base_t &>() + skip) && noexcept(derived_t{std::declval<base_t &>()}))
283  requires requires (base_t_ const i, difference_type const n) { i + n; } &&
284  std::constructible_from<derived_t, base_t_>
286  {
287  return derived_t{as_base() + skip};
288  }
289 
291  constexpr friend derived_t operator+(difference_type const skip, derived_t const & it)
292  noexcept(noexcept(skip + std::declval<base_t const &>()))
294  requires requires (base_t const i, difference_type const n) { n + i; } &&
295  std::constructible_from<derived_t, base_t>
297  {
298  return it + skip;
299  }
300 
303  template <typename base_t_ = base_t>
305  constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() -= skip))
307  requires requires (base_t_ i, difference_type const n) { i -= n; }
309  {
310  as_base() -= skip;
311  return *this_derived();
312  }
313 
316  template <typename base_t_ = base_t>
318  constexpr derived_t operator-(difference_type const skip) const
319  noexcept(noexcept(std::declval<base_t const &>() - skip) && noexcept(derived_t(std::declval<base_t &>())))
321  requires requires (base_t_ i, difference_type const n) { i - n; } &&
322  std::constructible_from<derived_t, base_t_>
324  {
325  return derived_t{as_base() - skip};
326  }
327 
329  constexpr difference_type operator-(derived_t const & rhs) const
330  noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
332  requires std::sized_sentinel_for<base_t, base_t>
334  {
335  return as_base() - rhs.as_base();
336  }
338 
343  constexpr reference operator*() noexcept(noexcept(*std::declval<base_t &>()))
345  requires std::indirectly_readable<base_t>
347  {
348  return *as_base();
349  }
350 
352  constexpr decltype(auto) operator*() const noexcept(noexcept(*std::declval<base_t const &>()))
354  requires std::indirectly_readable<base_t>
356  {
357  return *as_base();
358  }
359 
361  constexpr pointer operator->() noexcept(noexcept(*std::declval<base_t &>()))
363  requires std::input_iterator<base_t>
365  {
366  return &as_base();
367  }
368 
370  constexpr decltype(auto) operator->() const noexcept(noexcept(*std::declval<base_t const &>()))
372  requires std::input_iterator<base_t>
374  {
375  return &as_base();
376  }
377 
380  template <typename base_t_ = base_t>
382  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n)
383  noexcept(noexcept(std::declval<base_t &>()[0]))
385  requires requires (base_t_ i, difference_type const n) { i[n]; }
387  {
388  return as_base()[n];
389  }
390 
393  template <typename base_t_ = base_t>
395  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
396  noexcept(noexcept(std::declval<base_t const &>()[0]))
398  requires requires (base_t_ const i, difference_type const n) { i[n]; }
400  {
401  return as_base()[n];
402  }
404 
405 private:
408 
410  friend derived_t;
411 
413  constexpr base_t & as_base() & noexcept
414  {
415  if constexpr (wrap_base)
416  return member;
417  else
418  return *this;
419  }
420 
422  constexpr base_t const & as_base() const & noexcept
423  {
424  if constexpr (wrap_base)
425  return member;
426  else
427  return *this;
428  }
429 
431  constexpr derived_t * this_derived()
432  {
433  return static_cast<derived_t*>(this);
434  }
435 
437  constexpr derived_t const * this_derived() const
438  {
439  return static_cast<derived_t const *>(this);
440  }
441 };
442 
443 } // namespace seqan3::detail
Provides seqan3::detail::empty_type.
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
Provides various transformation traits for use on iterators.
Provides C++20 additions to the <iterator> header.
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