BioC++ core-0.7.0
The Modern C++ libraries for Bioinformatics.
 
Loading...
Searching...
No Matches
inherited_iterator_base.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2022 deCODE Genetics
3// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
4// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
5// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
6// shipped with this file and also available at: https://github.com/biocpp/biocpp-core/blob/main/LICENSE.md
7// -----------------------------------------------------------------------------------------------------
8
14#pragma once
15
16#include <cassert>
17#include <iterator>
18#include <type_traits>
19
22
23namespace bio::ranges::detail
24{
25
49template <typename derived_t, std::input_or_output_iterator base_t>
50class inherited_iterator_base :
51 public std::conditional_t<std::is_pointer_v<base_t> || !std::semiregular<base_t>, meta::detail::empty_type, base_t>
52{
53private:
55 static constexpr bool wrap_base = std::is_pointer_v<base_t> || !std::semiregular<base_t>;
56
57public:
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>;
72 using iterator_category = detail::iterator_category_tag_t<base_t>;
74 using iterator_concept = detail::iterator_concept_tag_t<base_t>;
76
81 constexpr inherited_iterator_base() noexcept(
82 std::is_nothrow_default_constructible_v<base_t>) = default;
83 constexpr inherited_iterator_base(inherited_iterator_base const & rhs) noexcept(
84 std::is_nothrow_copy_constructible_v<base_t>) = default;
85 constexpr inherited_iterator_base(inherited_iterator_base && rhs) noexcept(
86 std::is_nothrow_move_constructible_v<base_t>) = default;
87 constexpr inherited_iterator_base & operator=(inherited_iterator_base const & rhs) noexcept(
88 std::is_nothrow_copy_assignable_v<base_t>) = default;
89 constexpr inherited_iterator_base & operator=(inherited_iterator_base && rhs) noexcept(
90 std::is_nothrow_move_assignable_v<base_t>) = default;
91 ~inherited_iterator_base() 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>)
95 requires(!wrap_base)
96 : base_t{std::move(it)}
97 {}
98
100 constexpr inherited_iterator_base(base_t const & it) noexcept(std::is_copy_constructible_v<base_t>)
101 requires(!wrap_base)
102 : base_t{it}
103 {}
104
106 constexpr inherited_iterator_base(base_t it) noexcept
107 requires wrap_base
108 : member{std::move(it)}
109 {}
111
118 constexpr friend bool operator==(derived_t const & lhs, derived_t const & rhs) noexcept(
119 noexcept(std::declval<base_t &>() == std::declval<base_t &>()))
120 requires std::equality_comparable<base_t>
121 {
122 return *lhs.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 &>()))
128 requires std::totally_ordered<base_t>
129 {
130 return *this_to_base() < *rhs.this_to_base();
131 }
132
134 constexpr bool operator>(derived_t const & rhs) const
135 noexcept(noexcept(std::declval<base_t &>() > std::declval<base_t &>()))
136 requires std::totally_ordered<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 &>()))
144 requires std::totally_ordered<base_t>
145 {
146 return !(*this > rhs);
147 }
148
150 constexpr bool operator>=(derived_t const & rhs) const
151 noexcept(noexcept(std::declval<base_t &>() < std::declval<base_t &>()))
152 requires std::totally_ordered<base_t>
153 {
154 return !(*this < rhs);
155 }
157
164 template <typename base_t_ = base_t>
166 constexpr derived_t & operator++() noexcept(noexcept(++std::declval<base_t &>()))
167 requires(requires(base_t_ i) { ++i; })
168 {
169 ++(*this_to_base());
170 return *this_derived();
171 }
172
175 template <typename base_t_ = base_t>
177 constexpr auto operator++(int) noexcept(noexcept(std::declval<base_t &>()++))
178 requires(requires(base_t_ i) {
179 i++;
180 requires !std::same_as<decltype(i++), base_t_>;
181 })
182 {
183 return (*this_to_base())++;
184 }
185
188 template <typename base_t_ = base_t>
190 constexpr derived_t operator++(int) noexcept(
191 noexcept(std::declval<base_t &>()++) && noexcept(derived_t(std::declval<base_t &>())))
193 requires(requires(base_t_ i) {
194 i++;
195 {
196 i++
197 } -> std::same_as<base_t_>;
198 } && std::constructible_from<derived_t, base_t_>)
200 {
201 return derived_t{(*this_to_base())++};
202 }
203
206 template <typename base_t_ = base_t>
208 constexpr derived_t & operator--() noexcept(noexcept(--std::declval<base_t &>()))
209 requires(requires(base_t_ i) { --i; })
210 {
211 --(*this_to_base());
212 return *this_derived();
213 }
214
217 template <typename base_t_ = base_t>
219 constexpr derived_t operator--(int) noexcept(
220 noexcept(std::declval<base_t &>()--) && noexcept(derived_t{std::declval<base_t &>()}))
221 requires(requires(base_t_ i) { i--; } && std::constructible_from<derived_t, base_t_>)
222 {
223 return derived_t{(*this_to_base())--};
224 }
225
228 template <typename base_t_ = base_t>
230 constexpr derived_t & operator+=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() += skip))
231 requires(requires(base_t_ i, difference_type const n) { i += n; })
232 {
233 *this_to_base() += skip;
234 return *this_derived();
235 }
236
239 template <typename base_t_ = base_t>
241 constexpr derived_t operator+(difference_type const skip) const
242 noexcept(noexcept(std::declval<base_t &>() + skip) && noexcept(derived_t{std::declval<base_t &>()}))
243 requires(requires(base_t_ const i, difference_type const n) { i + n; } &&
244 std::constructible_from<derived_t, base_t_>)
245 {
246 return derived_t{*this_to_base() + skip};
247 }
248
250 constexpr friend derived_t operator+(difference_type const skip,
251 derived_t const & it) noexcept(noexcept(skip + std::declval<base_t const &>()))
252 requires(requires(base_t const i, difference_type const n) { n + i; } &&
253 std::constructible_from<derived_t, base_t>)
254 {
255 return derived_t{skip + static_cast<base_t const &>(it)};
256 }
257
260 template <typename base_t_ = base_t>
262 constexpr derived_t & operator-=(difference_type const skip) noexcept(noexcept(std::declval<base_t &>() -= skip))
263 requires(requires(base_t_ i, difference_type const n) { i -= n; })
264 {
265 *this_to_base() -= skip;
266 return *this_derived();
267 }
268
271 template <typename base_t_ = base_t>
273 constexpr derived_t operator-(difference_type const skip) const
274 noexcept(noexcept(std::declval<base_t const &>() - skip) && noexcept(derived_t(std::declval<base_t &>())))
275 requires(requires(base_t_ i, difference_type const n) { i - n; } && std::constructible_from<derived_t, base_t_>)
276 {
277 return derived_t{*this_to_base() - skip};
278 }
279
281 constexpr difference_type operator-(derived_t const rhs) const
282 noexcept(noexcept(std::declval<base_t &>() - std::declval<base_t &>()))
283 requires std::sized_sentinel_for<base_t, base_t>
284 {
285 return static_cast<difference_type>(*this_to_base() - *rhs.this_to_base());
286 }
288
293 constexpr reference operator*() noexcept(noexcept(*std::declval<base_t &>()))
294 requires std::indirectly_readable<base_t>
295 {
296 return **this_to_base();
297 }
298
300 constexpr decltype(auto) operator*() const noexcept(noexcept(*std::declval<base_t const &>()))
301 requires std::indirectly_readable<base_t>
302 {
303 return **this_to_base();
304 }
305
307 constexpr pointer operator->() noexcept(noexcept(*std::declval<base_t &>()))
308 requires std::input_iterator<base_t>
309 {
310 return &*this_to_base();
311 }
312
314 constexpr decltype(auto) operator->() const noexcept(noexcept(*std::declval<base_t const &>()))
315 requires std::input_iterator<base_t>
316 {
317 return &*this_to_base();
318 }
319
322 template <typename base_t_ = base_t>
324 constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) noexcept(
325 noexcept(std::declval<base_t &>()[0]))
326 requires(requires(base_t_ i, difference_type const n) { i[n]; })
327 {
328 return (*this_to_base())[n];
329 }
330
333 template <typename base_t_ = base_t>
335 constexpr decltype(auto) operator[](std::make_signed_t<difference_type> const n) const
336 noexcept(noexcept(std::declval<base_t const &>()[0]))
337 requires(requires(base_t_ const i, difference_type const n) { i[n]; })
338 {
339 return (*this_to_base())[n];
340 }
342
343private:
346
348 friend derived_t;
349
351 constexpr derived_t * this_derived() { return static_cast<derived_t *>(this); }
352
354 constexpr derived_t const * this_derived() const { return static_cast<derived_t const *>(this); }
355
357 constexpr base_t * this_to_base()
358 {
359 if constexpr (wrap_base)
360 return &member;
361 else
362 return static_cast<base_t *>(this);
363 }
364
366 constexpr base_t const * this_to_base() const
367 {
368 if constexpr (wrap_base)
369 return &member;
370 else
371 return static_cast<base_t const *>(this);
372 }
373};
374
375} // namespace bio::ranges::detail
Provides bio::meta::detail::empty_type.
T operator>(T... args)
Provides various transformation traits used by the range module.