SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
inherited_iterator_base.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 <type_traits>
17 
20 #include <seqan3/std/iterator>
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 {
53 private:
55  static constexpr bool wrap_base = std::is_pointer_v<base_t> || !std::semiregular<base_t>;
56 public:
62  using difference_type = typename std::iterator_traits<base_t>::difference_type;
65  using value_type = typename std::iterator_traits<base_t>::value_type;
67  using reference = typename std::iterator_traits<base_t>::reference;
69  using pointer = typename std::iterator_traits<base_t>::pointer;
71  using iterator_category = iterator_tag_t<base_t>;
73 
78  constexpr inherited_iterator_base()
79  noexcept(std::is_nothrow_default_constructible_v<base_t>) = default;
80  constexpr inherited_iterator_base(inherited_iterator_base const & rhs)
81  noexcept(std::is_nothrow_copy_constructible_v<base_t>) = default;
82  constexpr inherited_iterator_base(inherited_iterator_base && rhs)
83  noexcept(std::is_nothrow_move_constructible_v<base_t>) = default;
84  constexpr inherited_iterator_base & operator=(inherited_iterator_base const & rhs)
85  noexcept(std::is_nothrow_copy_assignable_v<base_t>) = default;
86  constexpr inherited_iterator_base & operator=(inherited_iterator_base && rhs)
87  noexcept(std::is_nothrow_move_assignable_v<base_t>) = default;
88  ~inherited_iterator_base()
89  noexcept(std::is_nothrow_destructible_v<base_t>) = default;
90 
92  constexpr inherited_iterator_base(base_t it) noexcept(std::is_nothrow_move_constructible_v<base_t>)
94  requires !wrap_base
96  : base_t{std::move(it)}
97  {}
98 
100  constexpr inherited_iterator_base(base_t it) noexcept
102  requires wrap_base
104  : member{std::move(it)}
105  {}
107 
113  constexpr bool operator==(derived_t const & rhs) const
115  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
117  requires std::equality_comparable<base_t>
119  {
120  return *this_to_base() == *rhs.this_to_base();
121  }
122 
124  constexpr bool operator!=(derived_t const & rhs) const
125  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
127  requires std::equality_comparable<base_t>
129  {
130  return !(*this == rhs);
131  }
132 
134  constexpr bool operator<(derived_t const & rhs) const
135  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
137  requires std::totally_ordered<base_t>
139  {
140  return *this_to_base() < *rhs.this_to_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::totally_ordered<base_t>
149  {
150  return *this_to_base() > *rhs.this_to_base();
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 !(*this > rhs);
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 !(*this < rhs);
171  }
173 
178  template <typename base_t_ = base_t>
182  constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
184  requires requires (base_t_ i) { ++i; }
186  {
187  ++(*this_to_base());
188  return *this_derived();
189  }
190 
193  template <typename base_t_ = base_t>
195  constexpr auto operator++(int) noexcept(noexcept(std::declval<base_t &>()++))
197  requires requires (base_t_ i) { i++; requires !std::same_as<decltype(i++), base_t_>; }
199  {
200  return (*this_to_base())++;
201  }
202 
205  template <typename base_t_ = base_t>
207  constexpr derived_t operator++(int) noexcept(noexcept(std::declval<base_t &>()++) &&
208  noexcept(derived_t(std::declval<base_t &>())))
210  requires requires (base_t_ i) { i++; requires std::same_as<decltype(i++), base_t_>; } &&
213  {
214  return derived_t{(*this_to_base())++};
215  }
216 
219  template <typename base_t_ = base_t>
221  constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
223  requires requires (base_t_ i) { --i; }
225  {
226  --(*this_to_base());
227  return *this_derived();
228  }
229 
232  template <typename base_t_ = base_t>
234  constexpr derived_t operator--(int) noexcept(noexcept(std::declval<base_t &>()--) &&
235  noexcept(derived_t{std::declval<base_t &>()}))
237  requires requires (base_t_ i) { i--; } && std::constructible_from<derived_t, base_t_>
239  {
240  return derived_t{(*this_to_base())--};
241  }
242 
245  template <typename base_t_ = base_t>
247  constexpr derived_t & operator+=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() += skip))
249  requires requires (base_t_ i, difference_type const n) { i += n; }
251  {
252  *this_to_base() += skip;
253  return *this_derived();
254  }
255 
258  template <typename base_t_ = base_t>
260  constexpr derived_t operator+(difference_type const skip) const
261  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; } &&
266  {
267  return derived_t{*this_to_base() + skip};
268  }
269 
271  constexpr friend derived_t operator+(difference_type const skip, derived_t const & it)
272  noexcept(noexcept(skip + std::declval<base_t const &>()))
274  requires requires (base_t const i, difference_type const n) { n + i; } &&
277  {
278  return derived_t{skip + static_cast<base_t const &>(it)};
279  }
280 
283  template <typename base_t_ = base_t>
285  constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() -= skip))
287  requires requires (base_t_ i, difference_type const n) { i -= n; }
289  {
290  *this_to_base() -= skip;
291  return *this_derived();
292  }
293 
296  template <typename base_t_ = base_t>
298  constexpr derived_t operator-(difference_type const skip) const
299  noexcept(noexcept(std::declval<base_t const &>() - skip) && noexcept(derived_t(std::declval<base_t &>())))
301  requires requires (base_t_ i, difference_type const n) { i - n; } &&
304  {
305  return derived_t{*this_to_base() - skip};
306  }
307 
309  constexpr difference_type operator-(derived_t const rhs) const
310  noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
312  requires std::sized_sentinel_for<base_t, base_t>
314  {
315  return static_cast<difference_type>(*this_to_base() - *rhs.this_to_base());
316  }
318 
322  constexpr reference operator*() noexcept(noexcept(*std::declval<base_t &>()))
325  requires std::readable<base_t>
327  {
328  return **this_to_base();
329  }
330 
332  constexpr decltype(auto) operator*() const noexcept(noexcept(*std::declval<base_t const &>()))
334  requires std::readable<base_t>
336  {
337  return **this_to_base();
338  }
339 
341  constexpr pointer operator->() noexcept(noexcept(*std::declval<base_t &>()))
343  requires std::input_iterator<base_t>
345  {
346  return &*this_to_base();
347  }
348 
350  constexpr decltype(auto) operator->() const noexcept(noexcept(*std::declval<base_t const &>()))
352  requires std::input_iterator<base_t>
354  {
355  return &*this_to_base();
356  }
357 
360  template <typename base_t_ = base_t>
362  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n)
363  noexcept(noexcept(std::declval<base_t &>()[0]))
365  requires requires (base_t_ i, difference_type const n) { i[n]; }
367  {
368  return (*this_to_base())[n];
369  }
370 
373  template <typename base_t_ = base_t>
375  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
376  noexcept(noexcept(std::declval<base_t const &>()[0]))
378  requires requires (base_t_ const i, difference_type const n) { i[n]; }
380  {
381  return (*this_to_base())[n];
382  }
384 
385 private:
388 
390  friend derived_t;
391 
393  constexpr derived_t * this_derived()
394  {
395  return static_cast<derived_t*>(this);
396  }
397 
399  constexpr derived_t const * this_derived() const
400  {
401  return static_cast<derived_t const *>(this);
402  }
403 
405  constexpr base_t * this_to_base()
406  {
407  if constexpr (wrap_base)
408  return &member;
409  else
410  return static_cast<base_t*>(this);
411  }
412 
414  constexpr base_t const * this_to_base() const
415  {
416  if constexpr (wrap_base)
417  return &member;
418  else
419  return static_cast<base_t const *>(this);
420  }
421 };
422 
423 } // namespace seqan3::detail
semiregular
Subsumes std::copyable and std::default_constructible.
constructible_from
The std::constructible_from concept specifies that a variable of type T can be initialized with the g...
std::rel_ops::operator!=
T operator!=(T... args)
iterator
Provides C++20 additions to the <iterator> header.
seqan3::views::move
const auto move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
totally_ordered
Requires std::equality_comparable and all remaing comparison operators (<, <=, >, >=).
same_as
The concept std::same_as<T, U> is satisfied if and only if T and U denote the same type.
std::iterator_traits
iterator.hpp
Provides various transformation traits for use on iterators.
empty_type.hpp
Provides seqan3::detail::empty_type.
std
SeqAn specific customisations in the standard namespace.
cassert
std::conditional_t
equality_comparable
The same as std::weakly_equality_comparable_with<t,t>.