28namespace seqan3::detail
48template <std::ranges::view urng_t,
bool or_throw>
49class view_take_exactly :
public std::ranges::view_interface<view_take_exactly<urng_t, or_throw>>
59 template <
bool const_range>
67 using iterator = basic_iterator<false>;
73 using const_iterator = basic_iterator<true>;
80 view_take_exactly() =
default;
81 view_take_exactly(view_take_exactly
const & rhs) =
default;
82 view_take_exactly(view_take_exactly && rhs) =
default;
83 view_take_exactly & operator=(view_take_exactly
const & rhs) =
default;
84 view_take_exactly & operator=(view_take_exactly && rhs) =
default;
85 ~view_take_exactly() =
default;
92 constexpr view_take_exactly(urng_t _urange,
size_t const _size) : urange{
std::
move(_urange)}, target_size{_size}
94 if constexpr (std::ranges::sized_range<urng_t>)
96 if (std::ranges::size(urange) < target_size)
98 if constexpr (or_throw)
101 "You are trying to construct a detail::take_exactly_or_throw from a range that is strictly "
106 target_size = std::ranges::size(urange);
118 template <std::ranges::viewable_range rng_t>
119 requires std::constructible_from<rng_t, std::views::all_t<rng_t>>
120 constexpr view_take_exactly(rng_t && _urange,
size_t const _size) :
121 view_take_exactly{
std::views::all(
std::
forward<rng_t>(_urange)), _size}
141 constexpr auto begin() noexcept
143 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
150 constexpr auto begin() const noexcept
153 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
176 constexpr auto end() noexcept
178 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
181 return std::ranges::end(urange);
185 constexpr auto end() const noexcept
188 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
191 return std::ranges::cend(urange);
206 constexpr auto size() const noexcept
214template <
typename urng_t,
bool or_throw = false>
215view_take_exactly(urng_t &&,
size_t) -> view_take_exactly<std::views::all_t<urng_t>, or_throw>;
219template <std::ranges::view urng_t,
bool or_throw>
220template <
bool const_range>
221class view_take_exactly<urng_t, or_throw>::basic_iterator :
222 public inherited_iterator_base<basic_iterator<const_range>, maybe_const_iterator_t<const_range, urng_t>>
226 using base_base_t = maybe_const_iterator_t<const_range, urng_t>;
228 using base_t = inherited_iterator_base<basic_iterator, maybe_const_iterator_t<const_range, urng_t>>;
231 using sentinel_type = maybe_const_sentinel_t<const_range, urng_t>;
247 basic_iterator() =
default;
248 basic_iterator(basic_iterator
const & rhs) =
default;
249 basic_iterator(basic_iterator && rhs) =
default;
250 basic_iterator & operator=(basic_iterator
const & rhs) =
default;
251 basic_iterator & operator=(basic_iterator && rhs) =
default;
252 ~basic_iterator() =
default;
255 constexpr basic_iterator(base_base_t it)
noexcept(
noexcept(base_t{it})) : base_t{std::move(it)}
259 constexpr basic_iterator(base_base_t it,
261 size_t const _max_pos,
262 view_take_exactly * host =
nullptr) noexcept(noexcept(base_t{it})) :
269 if constexpr (!std::forward_iterator<base_base_t>)
271 assert(host_ptr !=
nullptr);
276 using typename base_t::difference_type;
277 using typename base_t::reference;
285 constexpr basic_iterator & operator++() noexcept(noexcept(++
std::declval<base_t &>()))
287 base_t::operator++();
289 if constexpr (!std::forward_iterator<base_base_t>)
290 --host_ptr->target_size;
295 constexpr decltype(
auto)
operator++(
int)
noexcept(
noexcept(++std::declval<basic_iterator &>())
296 && (std::same_as<
decltype(std::declval<base_base_t &>()++),
void>
297 || std::is_nothrow_copy_constructible_v<basic_iterator>))
300 if constexpr (std::same_as<decltype(std::declval<base_base_t &>()++),
void>)
306 basic_iterator cpy{*
this};
313 constexpr basic_iterator & operator--() noexcept(noexcept(--
std::declval<base_base_t &>()))
314 requires
std::bidirectional_iterator<base_base_t>
316 base_t::operator--();
322 constexpr basic_iterator operator--(
int)
323 noexcept(
noexcept(--std::declval<basic_iterator &>()) && std::is_nothrow_copy_constructible_v<basic_iterator>)
324 requires std::bidirectional_iterator<base_base_t>
326 basic_iterator cpy{*
this};
332 constexpr basic_iterator & operator+=(difference_type
const skip)
333 noexcept(
noexcept(std::declval<base_t &>() += skip))
334 requires std::random_access_iterator<base_base_t>
336 base_t::operator+=(skip);
342 constexpr basic_iterator & operator-=(difference_type
const skip)
343 noexcept(
noexcept(std::declval<base_t &>() -= skip))
344 requires std::random_access_iterator<base_base_t>
346 base_t::operator-=(skip);
358 constexpr bool operator==(basic_iterator
const & rhs)
const
359 noexcept(!or_throw &&
noexcept(std::declval<base_base_t &>() == std::declval<base_base_t &>()))
360 requires std::forward_iterator<base_base_t>
362 return this->base() == rhs.base();
366 constexpr bool operator==(sentinel_type
const & rhs)
const
367 noexcept(!or_throw &&
noexcept(std::declval<base_base_t const &>() == std::declval<sentinel_type const &>()))
372 if (this->base() == rhs)
374 if constexpr (or_throw)
375 throw unexpected_end_of_input{
"Reached end of input before designated size."};
386 constexpr friend bool operator==(sentinel_type
const & lhs, basic_iterator
const & rhs)
387 noexcept(
noexcept(rhs == lhs))
393 constexpr bool operator!=(sentinel_type
const & rhs)
const
394 noexcept(
noexcept(std::declval<basic_iterator &>() == rhs))
396 return !(*
this == rhs);
400 constexpr bool operator!=(basic_iterator
const & rhs)
const
401 noexcept(
noexcept(std::declval<basic_iterator &>() == rhs))
402 requires std::forward_iterator<base_base_t>
404 return !(*
this == rhs);
408 constexpr friend bool operator!=(sentinel_type
const & lhs, basic_iterator
const & rhs)
409 noexcept(
noexcept(rhs != lhs))
425 noexcept(
noexcept(std::declval<base_base_t &>()[0]))
426 requires std::random_access_iterator<base_base_t>
428 return base_t::operator[](n);
440template <
bool or_throw>
441struct take_exactly_fn
444 constexpr auto operator()(
size_t const size)
const
446 return adaptor_from_functor{*
this,
size};
452 template <std::ranges::range urng_t>
453 constexpr auto operator()(urng_t && urange,
size_t target_size)
const
455 static_assert(std::ranges::viewable_range<urng_t>,
456 "The views::take adaptor can only be passed viewable_ranges, i.e. Views or &-to-non-View.");
459 if constexpr (std::ranges::sized_range<urng_t>)
461 if constexpr (or_throw)
463 if (target_size > std::ranges::size(urange))
466 "range that is strictly smaller."};
471 target_size = std::min<size_t>(target_size, std::ranges::size(urange));
479 return urange.substr(0, target_size);
482 else if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>,
std::basic_string>
483 && std::is_const_v<std::remove_reference_t<urng_t>>)
490 else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::contiguous_range<urng_t>
491 && std::ranges::sized_range<urng_t>)
495 return std::span{std::ranges::data(urange), target_size};
498 else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::random_access_range<urng_t>
499 && std::ranges::sized_range<urng_t>)
503 return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>{
511 return view_take_exactly<std::views::all_t<urng_t>, or_throw>{std::forward<urng_t>(urange), target_size};
522namespace seqan3::detail
573inline constexpr auto take_exactly = take_exactly_fn<false>{};
587inline constexpr auto take_exactly_or_throw = take_exactly_fn<true>{};
Provides seqan3::detail::adaptor_from_functor.
Provides various transformation traits used by the range module.
constexpr size_t size
The size of a type pack.
Definition type_pack/traits.hpp:143
Provides the seqan3::detail::inherited_iterator_base template.
Specifies requirements of an input range type for which the const version of that type satisfies the ...
Provides exceptions used in the I/O module.
Provides various transformation traits for use on iterators.
SeqAn specific customisations in the standard namespace.
Provides type traits for working with templates.
Additional non-standard concepts for ranges.