SeqAn3
The Modern C++ library for sequence analysis.
inherited_iterator_base.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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 
19 #include <seqan3/std/iterator>
20 
21 namespace seqan3::detail
22 {
23 
25 struct empty_type
26 {};
27 
51 template <typename derived_t, std::Iterator base_t>
52 class inherited_iterator_base : public std::conditional_t<std::is_pointer_v<base_t>, empty_type, base_t>
53 {
54 public:
60  using difference_type = typename std::iterator_traits<base_t>::difference_type;
63  using value_type = typename std::iterator_traits<base_t>::value_type;
65  using reference = typename std::iterator_traits<base_t>::reference;
67  using pointer = typename std::iterator_traits<base_t>::pointer;
69  using iterator_category = iterator_tag_t<base_t>;
71 
76  constexpr inherited_iterator_base()
77  noexcept(std::is_nothrow_default_constructible_v<base_t>) = default;
78  constexpr inherited_iterator_base(inherited_iterator_base const & rhs)
79  noexcept(std::is_nothrow_copy_constructible_v<base_t>) = default;
80  constexpr inherited_iterator_base(inherited_iterator_base && rhs)
81  noexcept(std::is_nothrow_move_constructible_v<base_t>) = default;
82  constexpr inherited_iterator_base & operator=(inherited_iterator_base const & rhs)
83  noexcept(std::is_nothrow_copy_assignable_v<base_t>) = default;
84  constexpr inherited_iterator_base & operator=(inherited_iterator_base && rhs)
85  noexcept(std::is_nothrow_move_assignable_v<base_t>) = default;
86  ~inherited_iterator_base()
87  noexcept(std::is_nothrow_destructible_v<base_t>) = default;
88 
90  constexpr inherited_iterator_base(base_t it) noexcept(std::is_nothrow_move_constructible_v<base_t>)
92  requires !std::is_pointer_v<base_t>
94  : base_t{std::move(it)}
95  {}
96 
98  constexpr inherited_iterator_base(base_t it) noexcept
100  requires std::is_pointer_v<base_t>
102  : member{std::move(it)}
103  {}
105 
111  constexpr bool operator==(derived_t const & rhs) const
113  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
115  requires std::EqualityComparable<base_t>
117  {
118  return *this_to_base() == *rhs.this_to_base();
119  }
120 
122  constexpr bool operator!=(derived_t const & rhs) const
123  noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
125  requires std::EqualityComparable<base_t>
127  {
128  return !(*this == rhs);
129  }
130 
132  constexpr bool operator<(derived_t const & rhs) const
133  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
135  requires std::StrictTotallyOrdered<base_t>
137  {
138  return *this_to_base() < *rhs.this_to_base();
139  }
140 
142  constexpr bool operator>(derived_t const & rhs) const
143  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
145  requires std::StrictTotallyOrdered<base_t>
147  {
148  return *this_to_base() > *rhs.this_to_base();
149  }
150 
152  constexpr bool operator<=(derived_t const & rhs) const
153  noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
155  requires std::StrictTotallyOrdered<base_t>
157  {
158  return !(*this > rhs);
159  }
160 
162  constexpr bool operator>=(derived_t const & rhs) const
163  noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
165  requires std::StrictTotallyOrdered<base_t>
167  {
168  return !(*this < rhs);
169  }
171 
176  constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
179  requires std::InputIterator<base_t>
181  {
182  ++(*this_to_base());
183  return *this_derived();
184  }
185 
187  constexpr derived_t operator++(int) noexcept(noexcept(++std::declval<derived_t &>()) &&
188  noexcept(derived_t(std::declval<base_t &>())))
190  requires std::InputIterator<base_t>
192  {
193  derived_t cpy{*this_to_base()};
194  ++(*this_derived());
195  return cpy;
196  }
197 
199  constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
201  requires std::BidirectionalIterator<base_t>
203  {
204  --(*this_to_base());
205  return *this_derived();
206  }
207 
209  constexpr derived_t operator--(int) noexcept(noexcept(--std::declval<derived_t &>()) &&
210  noexcept(derived_t{std::declval<base_t &>()}))
214  {
215  derived_t cpy{*this_to_base()};
216  --(*this_derived());
217  return cpy;
218  }
219 
221  constexpr derived_t & operator+=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() += skip))
225  {
226  *this_to_base() += skip;
227  return *this_derived();
228  }
229 
231  constexpr derived_t operator+(difference_type const skip) const
232  noexcept(noexcept(std::declval<derived_t &>() += skip) && noexcept(derived_t{std::declval<base_t &>()}))
236  {
237  derived_t cpy{*this_to_base()};
238  return cpy += skip;
239  }
240 
242  constexpr friend derived_t operator+(difference_type const skip, derived_t const & it)
243  noexcept(noexcept(it + skip))
247  {
248  return it + skip;
249  }
250 
252  constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<derived_t &>() += skip))
256  {
257  return *this_derived() += -skip;
258  }
259 
261  constexpr derived_t operator-(difference_type const skip) const
262  noexcept(noexcept(std::declval<derived_t &>() -= skip) && noexcept(derived_t(std::declval<base_t &>())))
264  requires std::RandomAccessIterator<base_t>
266  {
267  derived_t cpy{*this_to_base()};
268  return cpy -= skip;
269  }
270 
272  constexpr friend derived_t operator-(difference_type const skip, derived_t const & it)
273  noexcept(noexcept(std::declval<derived_t &>() - skip))
277  {
278  return it - skip;
279  }
280 
282  constexpr difference_type operator-(derived_t const rhs) const
283  noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
285  requires std::RandomAccessIterator<base_t>
287  {
288  assert(*rhs.this_to_base() <= *this_to_base());
289  return static_cast<difference_type>(*this_to_base() - *rhs.this_to_base());
290  }
292 
296  constexpr reference operator*() const noexcept(noexcept(*std::declval<base_t &>()))
299  requires std::InputIterator<base_t>
301  {
302  return **this_to_base();
303  }
304 
306  constexpr pointer operator->() const noexcept(noexcept(*std::declval<base_t &>()))
308  requires std::InputIterator<base_t>
310  {
311  return &*this_to_base();
312  }
313 
315  constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
316  noexcept(noexcept(*std::declval<derived_t &>()) && noexcept(std::declval<derived_t &>() + 3))
318  requires std::RandomAccessIterator<base_t>
320  {
321  return *(*this_derived() + n);
322  }
324 
325 private:
327  std::conditional_t<std::is_pointer_v<base_t>, base_t, empty_type> member;
328 
330  friend derived_t;
331 
333  constexpr derived_t * this_derived()
334  {
335  return static_cast<derived_t*>(this);
336  }
337 
339  constexpr derived_t const * this_derived() const
340  {
341  return static_cast<derived_t const *>(this);
342  }
343 
345  constexpr base_t * this_to_base()
346  {
347  if constexpr (std::is_pointer_v<base_t>)
348  return &member;
349  else
350  return static_cast<base_t*>(this);
351  }
352 
354  constexpr base_t const * this_to_base() const
355  {
356  if constexpr (std::is_pointer_v<base_t>)
357  return &member;
358  else
359  return static_cast<base_t const *>(this);
360  }
361 };
362 
363 } // namespace seqan3::detail
The concept RandomAccessIterator refines std::BidirectionalIterator by adding support for constant ti...
T operator!=(T... args)
Provides C++20 additions to the <iterator> header.
SeqAn specific customisations in the standard namespace.
Provides various transformation traits for use on iterators.
Definition: aligned_sequence_concept.hpp:35
The concept BidirectionalIterator refines std::ForwardIterator by adding the ability to move an itera...