32 namespace seqan3::detail
52 template <std::ranges::view urng_t,
bool exactly,
bool or_throw>
53 class view_take :
public std::ranges::view_interface<view_take<urng_t, exactly, or_throw>>
63 template <
typename rng_t>
70 using iterator = basic_iterator<urng_t>;
77 using const_iterator = basic_iterator<urng_t const>;
84 view_take() =
default;
85 view_take(view_take
const & rhs) =
default;
86 view_take(view_take && rhs) =
default;
87 view_take & operator=(view_take
const & rhs) =
default;
88 view_take & operator=(view_take && rhs) =
default;
89 ~view_take() =
default;
96 constexpr view_take(urng_t _urange,
size_t const _size)
97 : urange{
std::move(_urange)}, target_size{_size}
99 if constexpr (std::ranges::sized_range<urng_t>)
103 if constexpr (exactly && or_throw)
107 "You are trying to construct a views::take_exactly_or_throw from a range that is strictly "
125 template <std::ranges::viewable_range rng_t>
127 requires std::constructible_from<rng_t, std::views::all_t<rng_t>>
129 constexpr view_take(rng_t && _urange,
size_t const _size)
130 : view_take{std::views::all(std::forward<rng_t>(_urange)), _size}
150 constexpr
auto begin() noexcept
152 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
159 constexpr
auto begin() const noexcept
162 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
181 constexpr
auto end() noexcept
183 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
186 return std::ranges::end(urange);
190 constexpr
auto end() const noexcept
193 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
196 return std::ranges::cend(urange);
215 constexpr
auto size() const noexcept
216 requires exactly ||
std::ranges::sized_range<urng_t>
224 template <
typename urng_t,
225 bool exactly =
false,
226 bool or_throw =
false>
227 view_take(urng_t && ,
size_t) -> view_take<std::views::all_t<urng_t>, exactly, or_throw>;
231 template <std::ranges::view urng_t,
bool exactly,
bool or_throw>
232 template <
typename rng_t>
233 class view_take<urng_t, exactly, or_throw>::basic_iterator :
234 public inherited_iterator_base<basic_iterator<rng_t>, std::ranges::iterator_t<rng_t>>
238 using base_base_t = std::ranges::iterator_t<rng_t>;
240 using base_t = inherited_iterator_base<basic_iterator, std::ranges::iterator_t<rng_t>>;
243 using sentinel_type = std::ranges::sentinel_t<urng_t>;
259 basic_iterator() =
default;
260 basic_iterator(basic_iterator
const & rhs) =
default;
261 basic_iterator(basic_iterator && rhs) =
default;
262 basic_iterator & operator=(basic_iterator
const & rhs) =
default;
263 basic_iterator & operator=(basic_iterator && rhs) =
default;
264 ~basic_iterator() =
default;
267 constexpr basic_iterator(base_base_t
const & it) noexcept(noexcept(base_t{it})) :
272 constexpr basic_iterator(base_base_t it,
274 size_t const _max_pos,
275 view_take * host =
nullptr) noexcept(noexcept(base_t{it})) :
276 base_t{
std::move(it)}, pos{_pos}, max_pos(_max_pos)
294 using pointer = detail::iter_pointer_t<base_base_t>;
296 using iterator_category = detail::iterator_category_tag_t<base_base_t>;
298 using iterator_concept = detail::iterator_concept_tag_t<base_base_t>;
306 constexpr basic_iterator & operator++() noexcept(noexcept(++
std::declval<base_t &>()))
309 base_t::operator++();
311 if constexpr (exactly && !std::forward_iterator<base_base_t>)
312 --host_ptr->target_size;
317 constexpr basic_iterator operator++(
int) noexcept(noexcept(++std::declval<basic_iterator &>()) &&
318 std::is_nothrow_copy_constructible_v<basic_iterator>)
320 basic_iterator cpy{*
this};
326 constexpr basic_iterator & operator--() noexcept(noexcept(--
std::declval<base_base_t &>()))
328 requires
std::bidirectional_iterator<base_base_t>
331 base_t::operator--();
337 constexpr basic_iterator operator--(
int) noexcept(noexcept(--std::declval<basic_iterator &>()) &&
338 std::is_nothrow_copy_constructible_v<basic_iterator>)
340 requires std::bidirectional_iterator<base_base_t>
343 basic_iterator cpy{*
this};
349 constexpr basic_iterator & operator+=(difference_type
const skip)
350 noexcept(noexcept(std::declval<base_t &>() += skip))
352 requires std::random_access_iterator<base_base_t>
355 base_t::operator+=(skip);
361 constexpr basic_iterator & operator-=(difference_type
const skip)
362 noexcept(noexcept(std::declval<base_t &>() -= skip))
364 requires std::random_access_iterator<base_base_t>
367 base_t::operator-=(skip);
378 constexpr
bool operator==(basic_iterator
const & rhs)
const
380 noexcept(!or_throw && noexcept(std::declval<base_base_t &>() == std::declval<base_base_t &>()))
382 requires
std::forward_iterator<base_base_t>
385 return *base_t::this_to_base() == *rhs.this_to_base();
389 constexpr
bool operator==(sentinel_type
const & rhs)
const
390 noexcept(!or_throw && noexcept(std::declval<base_base_t const &>() == std::declval<sentinel_type const &>()))
395 if (*base_t::this_to_base() == rhs)
397 if constexpr (or_throw)
398 throw unexpected_end_of_input{
"Reached end of input before designated size."};
409 constexpr
friend bool operator==(sentinel_type
const & lhs, basic_iterator
const & rhs)
410 noexcept(noexcept(rhs == lhs))
416 constexpr
bool operator!=(sentinel_type
const & rhs)
const
417 noexcept(noexcept(std::declval<basic_iterator &>() == rhs))
419 return !(*
this == rhs);
423 constexpr
bool operator!=(basic_iterator
const & rhs)
const
424 noexcept(noexcept(std::declval<basic_iterator &>() == rhs))
426 requires std::forward_iterator<base_base_t>
429 return !(*
this == rhs);
433 constexpr
friend bool operator!=(sentinel_type
const & lhs, basic_iterator
const & rhs)
434 noexcept(noexcept(rhs != lhs))
450 noexcept(noexcept(std::declval<base_base_t &>()[0]))
452 requires
std::random_access_iterator<base_base_t>
455 return base_base_t::operator[](n);
467 template <
bool exactly,
bool or_throw>
471 constexpr
auto operator()(
size_t const size)
const
473 return adaptor_from_functor{*
this,
size};
479 template <std::ranges::range urng_t>
480 constexpr
auto operator()(urng_t && urange,
size_t target_size)
const
482 static_assert(std::ranges::viewable_range<urng_t>,
483 "The views::take adaptor can only be passed viewable_ranges, i.e. Views or &-to-non-View.");
486 if constexpr (std::ranges::sized_range<urng_t>)
488 if constexpr (or_throw)
493 "range that is strictly smaller."};
505 return urange.substr(0, target_size);
514 else if constexpr (std::ranges::borrowed_range<urng_t> &&
515 std::ranges::contiguous_range<urng_t> &&
516 std::ranges::sized_range<urng_t>)
518 return std::span{std::ranges::data(urange), target_size};
521 else if constexpr (std::ranges::borrowed_range<urng_t> &&
522 std::ranges::random_access_range<urng_t> &&
523 std::ranges::sized_range<urng_t>)
525 return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>
535 return view_take<std::views::all_t<urng_t>, exactly, or_throw>
537 std::forward<urng_t>(urange),
611 inline auto constexpr
take = detail::take_fn<false, false>{};