31namespace seqan3::detail
51template <std::ranges::view urng_t,
bool or_throw>
52class view_take_exactly :
public std::ranges::view_interface<view_take_exactly<urng_t, or_throw>>
62 template <
bool const_range>
70 using iterator = basic_iterator<false>;
76 using const_iterator = basic_iterator<true>;
83 view_take_exactly() =
default;
84 view_take_exactly(view_take_exactly
const & rhs) =
default;
85 view_take_exactly(view_take_exactly && rhs) =
default;
86 view_take_exactly & operator=(view_take_exactly
const & rhs) =
default;
87 view_take_exactly & operator=(view_take_exactly && rhs) =
default;
88 ~view_take_exactly() =
default;
95 constexpr view_take_exactly(urng_t _urange,
size_t const _size) : urange{
std::
move(_urange)}, target_size{_size}
97 if constexpr (std::ranges::sized_range<urng_t>)
101 if constexpr (or_throw)
104 "You are trying to construct a detail::take_exactly_or_throw from a range that is strictly "
121 template <std::ranges::viewable_range rng_t>
122 requires std::constructible_from<rng_t, std::views::all_t<rng_t>>
123 constexpr view_take_exactly(rng_t && _urange,
size_t const _size) :
124 view_take_exactly{
std::views::all(
std::
forward<rng_t>(_urange)), _size}
144 constexpr auto begin() noexcept
146 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
153 constexpr auto begin() const noexcept
156 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
179 constexpr auto end() noexcept
181 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
184 return std::ranges::end(urange);
188 constexpr auto end() const noexcept
191 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
194 return std::ranges::cend(urange);
209 constexpr auto size() const noexcept
217template <
typename urng_t,
bool or_throw = false>
218view_take_exactly(urng_t &&,
size_t) -> view_take_exactly<std::views::all_t<urng_t>, or_throw>;
222template <std::ranges::view urng_t,
bool or_throw>
223template <
bool const_range>
224class view_take_exactly<urng_t, or_throw>::basic_iterator :
225 public inherited_iterator_base<basic_iterator<const_range>, maybe_const_iterator_t<const_range, urng_t>>
229 using base_base_t = maybe_const_iterator_t<const_range, urng_t>;
231 using base_t = inherited_iterator_base<basic_iterator, maybe_const_iterator_t<const_range, urng_t>>;
234 using sentinel_type = maybe_const_sentinel_t<const_range, urng_t>;
250 basic_iterator() =
default;
251 basic_iterator(basic_iterator
const & rhs) =
default;
252 basic_iterator(basic_iterator && rhs) =
default;
253 basic_iterator & operator=(basic_iterator
const & rhs) =
default;
254 basic_iterator & operator=(basic_iterator && rhs) =
default;
255 ~basic_iterator() =
default;
258 constexpr basic_iterator(base_base_t
const & it)
noexcept(
noexcept(base_t{it})) : base_t{std::move(it)}
262 constexpr basic_iterator(base_base_t it,
264 size_t const _max_pos,
265 view_take_exactly * host =
nullptr) noexcept(noexcept(base_t{it})) :
272 if constexpr (!std::forward_iterator<base_base_t>)
274 assert(host_ptr !=
nullptr);
279 using typename base_t::difference_type;
280 using typename base_t::reference;
288 constexpr basic_iterator & operator++() noexcept(noexcept(++
std::declval<base_t &>()))
290 base_t::operator++();
292 if constexpr (!std::forward_iterator<base_base_t>)
293 --host_ptr->target_size;
298 constexpr decltype(
auto)
operator++(
int)
noexcept(
noexcept(++std::declval<basic_iterator &>())
299 && (std::same_as<
decltype(std::declval<base_base_t &>()++),
void>
300 || std::is_nothrow_copy_constructible_v<basic_iterator>))
303 if constexpr (std::same_as<decltype(std::declval<base_base_t &>()++),
void>)
309 basic_iterator cpy{*
this};
316 constexpr basic_iterator & operator--() noexcept(noexcept(--
std::declval<base_base_t &>()))
317 requires
std::bidirectional_iterator<base_base_t>
319 base_t::operator--();
325 constexpr basic_iterator operator--(
int)
noexcept(
noexcept(--std::declval<basic_iterator &>())
326 && std::is_nothrow_copy_constructible_v<basic_iterator>)
327 requires std::bidirectional_iterator<base_base_t>
329 basic_iterator cpy{*
this};
335 constexpr basic_iterator & operator+=(difference_type
const skip)
noexcept(
noexcept(std::declval<base_t &>() +=
337 requires std::random_access_iterator<base_base_t>
339 base_t::operator+=(skip);
345 constexpr basic_iterator & operator-=(difference_type
const skip)
noexcept(
noexcept(std::declval<base_t &>() -=
347 requires std::random_access_iterator<base_base_t>
349 base_t::operator-=(skip);
361 constexpr bool operator==(basic_iterator
const & rhs)
const
362 noexcept(!or_throw &&
noexcept(std::declval<base_base_t &>() == std::declval<base_base_t &>()))
363 requires std::forward_iterator<base_base_t>
365 return this->base() == rhs.base();
369 constexpr bool operator==(sentinel_type
const & rhs)
const
370 noexcept(!or_throw &&
noexcept(std::declval<base_base_t const &>() == std::declval<sentinel_type const &>()))
375 if (this->base() == rhs)
377 if constexpr (or_throw)
378 throw unexpected_end_of_input{
"Reached end of input before designated size."};
389 constexpr friend bool operator==(sentinel_type
const & lhs,
390 basic_iterator
const & rhs)
noexcept(
noexcept(rhs == lhs))
396 constexpr bool operator!=(sentinel_type
const & rhs)
const
397 noexcept(
noexcept(std::declval<basic_iterator &>() == rhs))
399 return !(*
this == rhs);
403 constexpr bool operator!=(basic_iterator
const & rhs)
const
404 noexcept(
noexcept(std::declval<basic_iterator &>() == rhs))
405 requires std::forward_iterator<base_base_t>
407 return !(*
this == rhs);
411 constexpr friend bool operator!=(sentinel_type
const & lhs,
412 basic_iterator
const & rhs)
noexcept(
noexcept(rhs != lhs))
428 noexcept(
noexcept(std::declval<base_base_t &>()[0]))
429 requires std::random_access_iterator<base_base_t>
431 return base_t::operator[](n);
443template <
bool or_throw>
444struct take_exactly_fn
447 constexpr auto operator()(
size_t const size)
const
449 return adaptor_from_functor{*
this,
size};
455 template <std::ranges::range urng_t>
456 constexpr auto operator()(urng_t && urange,
size_t target_size)
const
458 static_assert(std::ranges::viewable_range<urng_t>,
459 "The views::take adaptor can only be passed viewable_ranges, i.e. Views or &-to-non-View.");
462 if constexpr (std::ranges::sized_range<urng_t>)
464 if constexpr (or_throw)
469 "range that is strictly smaller."};
482 return urange.substr(0, target_size);
485 else if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>,
std::basic_string>
486 && std::is_const_v<std::remove_reference_t<urng_t>>)
493 else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::contiguous_range<urng_t>
494 && std::ranges::sized_range<urng_t>)
498 return std::span{std::ranges::data(urange), target_size};
501 else if constexpr (std::ranges::borrowed_range<urng_t> && std::ranges::random_access_range<urng_t>
502 && std::ranges::sized_range<urng_t>)
506 return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>{
514 return view_take_exactly<std::views::all_t<urng_t>, or_throw>{std::forward<urng_t>(urange), target_size};
525namespace seqan3::detail
576inline constexpr auto take_exactly = take_exactly_fn<false>{};
590inline 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: traits.hpp:146
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.