SeqAn3  3.0.2
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 = std::iter_difference_t<base_t>;
65  using value_type = std::iter_value_t<base_t>;
67  using reference = std::iter_reference_t<base_t>;
69  using pointer = detail::iter_pointer_t<base_t>;
71  using iterator_category = detail::iterator_category_tag_t<base_t>;
73  using iterator_concept = detail::iterator_concept_tag_t<base_t>;
75 
80  constexpr inherited_iterator_base()
81  noexcept(std::is_nothrow_default_constructible_v<base_t>) = default;
82  constexpr inherited_iterator_base(inherited_iterator_base const & rhs)
83  noexcept(std::is_nothrow_copy_constructible_v<base_t>) = default;
84  constexpr inherited_iterator_base(inherited_iterator_base && rhs)
85  noexcept(std::is_nothrow_move_constructible_v<base_t>) = default;
86  constexpr inherited_iterator_base & operator=(inherited_iterator_base const & rhs)
87  noexcept(std::is_nothrow_copy_assignable_v<base_t>) = default;
88  constexpr inherited_iterator_base & operator=(inherited_iterator_base && rhs)
89  noexcept(std::is_nothrow_move_assignable_v<base_t>) = default;
90  ~inherited_iterator_base()
91  noexcept(std::is_nothrow_destructible_v<base_t>) = default;
92 
94  constexpr inherited_iterator_base(base_t it) noexcept(std::is_nothrow_move_constructible_v<base_t>)
96  requires (!wrap_base)
98  : base_t{std::move(it)}
99  {}
100 
102  constexpr inherited_iterator_base(base_t it) noexcept
104  requires wrap_base
106  : member{std::move(it)}
107  {}
109 
115  constexpr bool operator==(derived_t const & rhs) const
117  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
119  requires std::equality_comparable<base_t>
121  {
122  return *this_to_base() == *rhs.this_to_base();
123  }
124 
126  constexpr bool operator!=(derived_t const & rhs) const
127  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
129  requires std::equality_comparable<base_t>
131  {
132  return !(*this == rhs);
133  }
134 
136  constexpr bool operator<(derived_t const & rhs) const
137  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
139  requires std::totally_ordered<base_t>
141  {
142  return *this_to_base() < *rhs.this_to_base();
143  }
144 
146  constexpr bool operator>(derived_t const & rhs) const
147  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
149  requires std::totally_ordered<base_t>
151  {
152  return *this_to_base() > *rhs.this_to_base();
153  }
154 
156  constexpr bool operator<=(derived_t const & rhs) const
157  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
159  requires std::totally_ordered<base_t>
161  {
162  return !(*this > rhs);
163  }
164 
166  constexpr bool operator>=(derived_t const & rhs) const
167  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
169  requires std::totally_ordered<base_t>
171  {
172  return !(*this < rhs);
173  }
175 
180  template <typename base_t_ = base_t>
184  constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
186  requires requires (base_t_ i) { ++i; }
188  {
189  ++(*this_to_base());
190  return *this_derived();
191  }
192 
195  template <typename base_t_ = base_t>
197  constexpr auto operator++(int) noexcept(noexcept(std::declval<base_t &>()++))
199  requires requires (base_t_ i) { i++; requires !std::same_as<decltype(i++), base_t_>; }
201  {
202  return (*this_to_base())++;
203  }
204 
207  template <typename base_t_ = base_t>
209  constexpr derived_t operator++(int) noexcept(noexcept(std::declval<base_t &>()++) &&
210  noexcept(derived_t(std::declval<base_t &>())))
212  requires requires (base_t_ i) { i++; SEQAN3_RETURN_TYPE_CONSTRAINT(i++, std::same_as, base_t_); } &&
213  std::constructible_from<derived_t, base_t_>
215  {
216  return derived_t{(*this_to_base())++};
217  }
218 
221  template <typename base_t_ = base_t>
223  constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
225  requires requires (base_t_ i) { --i; }
227  {
228  --(*this_to_base());
229  return *this_derived();
230  }
231 
234  template <typename base_t_ = base_t>
236  constexpr derived_t operator--(int) noexcept(noexcept(std::declval<base_t &>()--) &&
237  noexcept(derived_t{std::declval<base_t &>()}))
239  requires requires (base_t_ i) { i--; } && std::constructible_from<derived_t, base_t_>
241  {
242  return derived_t{(*this_to_base())--};
243  }
244 
247  template <typename base_t_ = base_t>
249  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; }
253  {
254  *this_to_base() += skip;
255  return *this_derived();
256  }
257 
260  template <typename base_t_ = base_t>
262  constexpr derived_t operator+(difference_type const skip) const
263  noexcept(noexcept(std::declval<base_t &>() + skip) && noexcept(derived_t{std::declval<base_t &>()}))
265  requires requires (base_t_ const i, difference_type const n) { i + n; } &&
266  std::constructible_from<derived_t, base_t_>
268  {
269  return derived_t{*this_to_base() + skip};
270  }
271 
273  constexpr friend derived_t operator+(difference_type const skip, derived_t const & it)
274  noexcept(noexcept(skip + std::declval<base_t const &>()))
276  requires requires (base_t const i, difference_type const n) { n + i; } &&
277  std::constructible_from<derived_t, base_t>
279  {
280  return derived_t{skip + static_cast<base_t const &>(it)};
281  }
282 
285  template <typename base_t_ = base_t>
287  constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() -= skip))
289  requires requires (base_t_ i, difference_type const n) { i -= n; }
291  {
292  *this_to_base() -= skip;
293  return *this_derived();
294  }
295 
298  template <typename base_t_ = base_t>
300  constexpr derived_t operator-(difference_type const skip) const
301  noexcept(noexcept(std::declval<base_t const &>() - skip) && noexcept(derived_t(std::declval<base_t &>())))
303  requires requires (base_t_ i, difference_type const n) { i - n; } &&
304  std::constructible_from<derived_t, base_t_>
306  {
307  return derived_t{*this_to_base() - skip};
308  }
309 
311  constexpr difference_type operator-(derived_t const rhs) const
312  noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
314  requires std::sized_sentinel_for<base_t, base_t>
316  {
317  return static_cast<difference_type>(*this_to_base() - *rhs.this_to_base());
318  }
320 
324  constexpr reference operator*() noexcept(noexcept(*std::declval<base_t &>()))
327  requires std::indirectly_readable<base_t>
329  {
330  return **this_to_base();
331  }
332 
334  constexpr decltype(auto) operator*() const noexcept(noexcept(*std::declval<base_t const &>()))
336  requires std::indirectly_readable<base_t>
338  {
339  return **this_to_base();
340  }
341 
343  constexpr pointer operator->() noexcept(noexcept(*std::declval<base_t &>()))
345  requires std::input_iterator<base_t>
347  {
348  return &*this_to_base();
349  }
350 
352  constexpr decltype(auto) operator->() const noexcept(noexcept(*std::declval<base_t const &>()))
354  requires std::input_iterator<base_t>
356  {
357  return &*this_to_base();
358  }
359 
362  template <typename base_t_ = base_t>
364  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n)
365  noexcept(noexcept(std::declval<base_t &>()[0]))
367  requires requires (base_t_ i, difference_type const n) { i[n]; }
369  {
370  return (*this_to_base())[n];
371  }
372 
375  template <typename base_t_ = base_t>
377  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
378  noexcept(noexcept(std::declval<base_t const &>()[0]))
380  requires requires (base_t_ const i, difference_type const n) { i[n]; }
382  {
383  return (*this_to_base())[n];
384  }
386 
387 private:
390 
392  friend derived_t;
393 
395  constexpr derived_t * this_derived()
396  {
397  return static_cast<derived_t*>(this);
398  }
399 
401  constexpr derived_t const * this_derived() const
402  {
403  return static_cast<derived_t const *>(this);
404  }
405 
407  constexpr base_t * this_to_base()
408  {
409  if constexpr (wrap_base)
410  return &member;
411  else
412  return static_cast<base_t*>(this);
413  }
414 
416  constexpr base_t const * this_to_base() const
417  {
418  if constexpr (wrap_base)
419  return &member;
420  else
421  return static_cast<base_t const *>(this);
422  }
423 };
424 
425 } // namespace seqan3::detail
std::rel_ops::operator!=
T operator!=(T... args)
iterator
Provides C++20 additions to the <iterator> header.
seqan3::views::move
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
SEQAN3_RETURN_TYPE_CONSTRAINT
#define SEQAN3_RETURN_TYPE_CONSTRAINT(expression, concept_name,...)
Same as writing {expression} -> concept_name<type1[, ...]> in a concept definition.
Definition: platform.hpp:57
std::iter_difference_t
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