16 #include <type_traits>
22 namespace seqan3::detail
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>,
71 using iterator_category = iterator_tag_t<base_t>;
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;
92 constexpr inherited_iterator_base(base_t it) noexcept(
std::is_nothrow_move_constructible_v<base_t>)
100 constexpr inherited_iterator_base(base_t it) noexcept
113 constexpr
bool operator==(derived_t
const & rhs)
const
115 noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
120 return *this_to_base() == *rhs.this_to_base();
124 constexpr
bool operator!=(derived_t
const & rhs)
const
125 noexcept(noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
130 return !(*
this == rhs);
134 constexpr
bool operator<(derived_t
const & rhs)
const
135 noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
140 return *this_to_base() < *rhs.this_to_base();
144 constexpr
bool operator>(derived_t
const & rhs)
const
145 noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
150 return *this_to_base() > *rhs.this_to_base();
154 constexpr
bool operator<=(derived_t
const & rhs)
const
155 noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
160 return !(*
this > rhs);
164 constexpr
bool operator>=(derived_t
const & rhs)
const
165 noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
170 return !(*
this < rhs);
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; }
188 return *this_derived();
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_>; }
200 return (*this_to_base())++;
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_>; } &&
214 return derived_t{(*this_to_base())++};
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; }
227 return *this_derived();
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 &>()}))
240 return derived_t{(*this_to_base())--};
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; }
252 *this_to_base() += skip;
253 return *this_derived();
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; } &&
267 return derived_t{*this_to_base() + skip};
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; } &&
278 return derived_t{skip + static_cast<base_t const &>(it)};
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; }
290 *this_to_base() -= skip;
291 return *this_derived();
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; } &&
305 return derived_t{*this_to_base() - skip};
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>
315 return static_cast<difference_type>(*this_to_base() - *rhs.this_to_base());
322 constexpr reference operator*() noexcept(noexcept(*
std::declval<base_t &>()))
325 requires
std::readable<base_t>
328 return **this_to_base();
332 constexpr decltype(
auto) operator*() const noexcept(noexcept(*
std::declval<base_t const &>()))
334 requires
std::readable<base_t>
337 return **this_to_base();
341 constexpr pointer operator->() noexcept(noexcept(*
std::declval<base_t &>()))
343 requires
std::input_iterator<base_t>
346 return &*this_to_base();
350 constexpr decltype(
auto) operator->() const noexcept(noexcept(*
std::declval<base_t const &>()))
352 requires
std::input_iterator<base_t>
355 return &*this_to_base();
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]; }
368 return (*this_to_base())[n];
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]; }
381 return (*this_to_base())[n];
393 constexpr derived_t * this_derived()
395 return static_cast<derived_t*>(
this);
399 constexpr derived_t
const * this_derived()
const
401 return static_cast<derived_t const *>(
this);
405 constexpr base_t * this_to_base()
407 if constexpr (wrap_base)
410 return static_cast<base_t*>(
this);
414 constexpr base_t
const * this_to_base()
const
416 if constexpr (wrap_base)
419 return static_cast<base_t const *>(
this);