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)
96 : urange{
std::move(_urange)}, target_size{_size}
98 if constexpr (std::ranges::sized_range<urng_t>)
102 if constexpr (or_throw)
106 "You are trying to construct a detail::take_exactly_or_throw from a range that is strictly "
124 template <std::ranges::viewable_range rng_t>
126 requires std::constructible_from<rng_t, std::views::all_t<rng_t>>
128 constexpr view_take_exactly(rng_t && _urange,
size_t const _size)
129 : view_take_exactly{
std::views::all(
std::
forward<rng_t>(_urange)), _size}
149 constexpr auto begin() noexcept
151 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
152 return std::ranges::begin(urange);
158 constexpr auto begin() const noexcept
161 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
162 return std::ranges::cbegin(urange);
180 constexpr auto end() noexcept
182 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
183 return std::ranges::begin(urange) + target_size;
185 return std::ranges::end(urange);
189 constexpr auto end() const noexcept
192 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>)
193 return std::ranges::cbegin(urange) + target_size;
195 return std::ranges::cend(urange);
210 constexpr auto size() const noexcept
218template <
typename urng_t,
219 bool or_throw =
false>
220view_take_exactly(urng_t && ,
size_t) -> view_take_exactly<std::views::all_t<urng_t>, or_throw>;
224template <std::ranges::view urng_t,
bool or_throw>
225template <
bool const_range>
226class view_take_exactly<urng_t, or_throw>::basic_iterator :
227 public inherited_iterator_base<basic_iterator<const_range>, maybe_const_iterator_t<const_range, urng_t>>
231 using base_base_t = maybe_const_iterator_t<const_range, urng_t>;
233 using base_t = inherited_iterator_base<basic_iterator, maybe_const_iterator_t<const_range, urng_t>>;
236 using sentinel_type = maybe_const_sentinel_t<const_range, urng_t>;
252 basic_iterator() =
default;
253 basic_iterator(basic_iterator
const & rhs) =
default;
254 basic_iterator(basic_iterator && rhs) =
default;
255 basic_iterator & operator=(basic_iterator
const & rhs) =
default;
256 basic_iterator & operator=(basic_iterator && rhs) =
default;
257 ~basic_iterator() =
default;
260 constexpr basic_iterator(base_base_t
const & it)
noexcept(
noexcept(base_t{it})) :
261 base_t{std::move(it)}
265 constexpr basic_iterator(base_base_t it,
267 size_t const _max_pos,
268 view_take_exactly * host =
nullptr) noexcept(noexcept(base_t{it})) :
269 base_t{
std::move(it)}, pos{_pos}, max_pos(_max_pos)
275 using typename base_t::difference_type;
276 using typename base_t::reference;
284 constexpr basic_iterator & operator++() noexcept(noexcept(++
std::declval<base_t &>()))
286 base_t::operator++();
288 if constexpr (!std::forward_iterator<base_base_t>)
289 --host_ptr->target_size;
294 constexpr basic_iterator operator++(
int)
noexcept(
noexcept(++std::declval<basic_iterator &>()) &&
295 std::is_nothrow_copy_constructible_v<basic_iterator>)
297 basic_iterator cpy{*
this};
303 constexpr basic_iterator & operator--() noexcept(noexcept(--
std::declval<base_base_t &>()))
305 requires
std::bidirectional_iterator<base_base_t>
308 base_t::operator--();
314 constexpr basic_iterator operator--(
int)
noexcept(
noexcept(--std::declval<basic_iterator &>()) &&
315 std::is_nothrow_copy_constructible_v<basic_iterator>)
317 requires std::bidirectional_iterator<base_base_t>
320 basic_iterator cpy{*
this};
326 constexpr basic_iterator & operator+=(difference_type
const skip)
327 noexcept(
noexcept(std::declval<base_t &>() += skip))
329 requires std::random_access_iterator<base_base_t>
332 base_t::operator+=(skip);
338 constexpr basic_iterator & operator-=(difference_type
const skip)
339 noexcept(
noexcept(std::declval<base_t &>() -= skip))
341 requires std::random_access_iterator<base_base_t>
344 base_t::operator-=(skip);
356 constexpr bool operator==(basic_iterator
const & rhs)
const
357 noexcept(!or_throw &&
noexcept(std::declval<base_base_t &>() == std::declval<base_base_t &>()))
359 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))
403 requires std::forward_iterator<base_base_t>
406 return !(*
this == rhs);
410 constexpr friend bool operator!=(sentinel_type
const & lhs, basic_iterator
const & rhs)
411 noexcept(
noexcept(rhs != lhs))
427 noexcept(
noexcept(std::declval<base_base_t &>()[0]))
429 requires std::random_access_iterator<base_base_t>
432 return base_t::operator[](n);
444template <
bool or_throw>
445struct take_exactly_fn
448 constexpr auto operator()(
size_t const size)
const
450 return adaptor_from_functor{*
this,
size};
456 template <std::ranges::range urng_t>
457 constexpr auto operator()(urng_t && urange,
size_t target_size)
const
459 static_assert(std::ranges::viewable_range<urng_t>,
460 "The views::take adaptor can only be passed viewable_ranges, i.e. Views or &-to-non-View.");
463 if constexpr (std::ranges::sized_range<urng_t>)
465 if constexpr (or_throw)
470 "range that is strictly smaller."};
483 return urange.substr(0, target_size);
486 else if constexpr (is_type_specialisation_of_v<std::remove_cvref_t<urng_t>,
std::basic_string> &&
487 std::is_const_v<std::remove_reference_t<urng_t>>)
494 else if constexpr (std::ranges::borrowed_range<urng_t> &&
495 std::ranges::contiguous_range<urng_t> &&
496 std::ranges::sized_range<urng_t>)
500 return std::span{std::ranges::data(urange), target_size};
503 else if constexpr (std::ranges::borrowed_range<urng_t> &&
504 std::ranges::random_access_range<urng_t> &&
505 std::ranges::sized_range<urng_t>)
509 return std::ranges::subrange<std::ranges::iterator_t<urng_t>, std::ranges::iterator_t<urng_t>>
519 return view_take_exactly<std::views::all_t<urng_t>, or_throw>
521 std::forward<urng_t>(urange),
534namespace seqan3::detail
585inline auto constexpr take_exactly = take_exactly_fn<false>{};
599inline auto constexpr take_exactly_or_throw = take_exactly_fn<true>{};
Provides seqan3::detail::adaptor_from_functor.
The <algorithm> header from C++20's standard library.
The <concepts> header from C++20's standard library.
Provides various transformation traits used by the range module.
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
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.
The <iterator> header from C++20's standard library.
SeqAn specific customisations in the standard namespace.
The <ranges> header from C++20's standard library.
Provides std::span from the C++20 standard library.
Provides type traits for working with templates.
The <type_traits> header from C++20's standard library.
Additional non-standard concepts for ranges.