Skip to content

Commit 1148ce1

Browse files
authored
Merge pull request #3014 from eseiler/fix/chunk
[FIX] chunk_view using 16 bit integers
2 parents 37916bc + f64ed67 commit 1148ce1

File tree

2 files changed

+37
-17
lines changed

2 files changed

+37
-17
lines changed

include/seqan3/utility/views/chunk.hpp

+29-17
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class chunk_view : public std::ranges::view_interface<chunk_view<urng_t>>
4545
urng_t urange;
4646

4747
//!\brief The chunk size to use.
48-
uint16_t chunk_size;
48+
std::ranges::range_difference_t<urng_t> chunk_size;
4949

5050
// The iterator type if `urng_t` is a pure input range. See class definition for details.
5151
template <bool const_range>
@@ -69,11 +69,11 @@ class chunk_view : public std::ranges::view_interface<chunk_view<urng_t>>
6969
~chunk_view() = default; //!< Defaulted.
7070

7171
/*!\brief Construct from a view and the chunk size.
72-
* \param[in] underlying_range The underlying range to divide into chunks.
72+
* \param[in] urng The underlying range to divide into chunks.
7373
* \param[in] size_of_chunk The size of the chunks, e.g., the length of the subrange returned at each position.
7474
*/
75-
constexpr explicit chunk_view(urng_t underlying_range, uint16_t const size_of_chunk) :
76-
urange{std::move(underlying_range)},
75+
constexpr explicit chunk_view(urng_t urng, std::ranges::range_difference_t<urng_t> const size_of_chunk) :
76+
urange{std::move(urng)},
7777
chunk_size{size_of_chunk}
7878
{}
7979
//!\}
@@ -161,7 +161,7 @@ class chunk_view : public std::ranges::view_interface<chunk_view<urng_t>>
161161

162162
//!\brief A deduction guide for the view class template.
163163
template <std::ranges::range rng_t>
164-
chunk_view(rng_t &&, uint16_t const &) -> chunk_view<seqan3::detail::all_t<rng_t>>;
164+
chunk_view(rng_t &&, std::ranges::range_difference_t<rng_t> const &) -> chunk_view<seqan3::detail::all_t<rng_t>>;
165165

166166
// ---------------------------------------------------------------------------------------------------------------------
167167
// chunk_view iterators (basic_input_iterator and basic_iterator)
@@ -319,7 +319,9 @@ class chunk_view<urng_t>::basic_input_iterator :
319319
*
320320
* Constant.
321321
*/
322-
constexpr explicit basic_input_iterator(urng_it_t it_begin, sentinel_t it_end, uint16_t const size_of_chunk) :
322+
constexpr explicit basic_input_iterator(urng_it_t it_begin,
323+
sentinel_t it_end,
324+
std::ranges::range_difference_t<urng_t> const size_of_chunk) :
323325
chunk_size{size_of_chunk},
324326
remaining{size_of_chunk},
325327
urng_begin{std::move(it_begin)},
@@ -374,10 +376,10 @@ class chunk_view<urng_t>::basic_input_iterator :
374376

375377
private:
376378
//!\brief The chunk size, e.g., the length of the subrange returned by this iterator.
377-
uint16_t chunk_size;
379+
std::ranges::range_difference_t<urng_t> chunk_size;
378380

379381
//!\brief The remaining elements in the chunk.
380-
uint16_t remaining;
382+
std::ranges::range_difference_t<urng_t> remaining;
381383

382384
//!\brief Points to the start of the underlying range.
383385
urng_it_t urng_begin;
@@ -469,7 +471,9 @@ class chunk_view<urng_t>::basic_iterator : public maybe_iterator_category<maybe_
469471
*
470472
* Linear in chunk_size for non-random_access ranges. Constant else.
471473
*/
472-
constexpr explicit basic_iterator(it_t it_start, sentinel_t it_end, uint16_t const size_of_chunk) :
474+
constexpr explicit basic_iterator(it_t it_start,
475+
sentinel_t it_end,
476+
std::ranges::range_difference_t<urng_t> const size_of_chunk) :
473477
chunk_size{size_of_chunk},
474478
urng_begin{std::move(it_start)},
475479
urng_end{std::move(it_end)}
@@ -675,7 +679,7 @@ class chunk_view<urng_t>::basic_iterator : public maybe_iterator_category<maybe_
675679

676680
private:
677681
//!\brief The chunk size, e.g. the length of the subrange returned by this iterator.
678-
uint16_t chunk_size;
682+
std::ranges::range_difference_t<urng_t> chunk_size;
679683

680684
//!\brief Points to the start of the underlying range.
681685
it_t urng_begin;
@@ -709,8 +713,12 @@ class chunk_view<urng_t>::basic_iterator : public maybe_iterator_category<maybe_
709713
}
710714
else // We need to increment one by one to not cross urng_end.
711715
{
712-
for (uint16_t increments{}; increments != chunk_size && start_of_chunk != urng_end; ++increments)
716+
for (std::ranges::range_difference_t<urng_t> increments{};
717+
increments != chunk_size && start_of_chunk != urng_end;
718+
++increments)
719+
{
713720
++start_of_chunk;
721+
}
714722

715723
return start_of_chunk;
716724
}
@@ -739,8 +747,12 @@ class chunk_view<urng_t>::basic_iterator : public maybe_iterator_category<maybe_
739747
}
740748
else // We need to decrement one by one to not cross urng_begin.
741749
{
742-
for (uint16_t decrements{}; decrements != chunk_size && end_of_chunk != urng_begin; ++decrements)
750+
for (std::ranges::range_difference_t<urng_t> decrements{};
751+
decrements != chunk_size && end_of_chunk != urng_begin;
752+
++decrements)
753+
{
743754
--end_of_chunk;
755+
}
744756

745757
return end_of_chunk;
746758
}
@@ -756,7 +768,7 @@ class chunk_view<urng_t>::basic_iterator : public maybe_iterator_category<maybe_
756768
struct chunk_fn
757769
{
758770
//!\brief Store the `chunk_size` and return a range adaptor closure object.
759-
constexpr auto operator()(uint16_t const chunk_size) const
771+
constexpr auto operator()(std::ptrdiff_t const chunk_size) const
760772
{
761773
return adaptor_from_functor{*this, chunk_size};
762774
}
@@ -766,13 +778,13 @@ struct chunk_fn
766778
* \param[in] chunk_size The chunk size, e.g. the length of the subrange returned by this iterator.
767779
* \returns A range of subranges.
768780
*/
769-
template <std::ranges::range underlying_range_t>
770-
constexpr auto operator()(underlying_range_t && urange, uint16_t const chunk_size) const
781+
template <std::ranges::range urng_t>
782+
constexpr auto operator()(urng_t && urange, std::ranges::range_difference_t<urng_t> const chunk_size) const
771783
{
772-
static_assert(std::ranges::input_range<underlying_range_t>,
784+
static_assert(std::ranges::input_range<urng_t>,
773785
"The range parameter to views::chunk must model std::ranges::input_range.");
774786

775-
return chunk_view{std::forward<underlying_range_t>(urange), chunk_size};
787+
return chunk_view{std::forward<urng_t>(urange), chunk_size};
776788
}
777789
};
778790

test/unit/utility/views/chunk_test.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,11 @@ TYPED_TEST(chunk_view_test, use_on_temporaries)
184184
EXPECT_EQ(i, 4u);
185185
}
186186
}
187+
188+
TYPED_TEST(chunk_view_test, big_chunk)
189+
{
190+
// Check that a very big number (1ULL<<42) can be stored as chunk_size inside the chunk_view.
191+
// error: conversion from ‘long long unsigned int’ to ‘uint16_t’ {aka ‘short unsigned int’} changes value
192+
// from ‘4398046511104’ to ‘0’ [-Werror=overflow]
193+
[[maybe_unused]] auto v = this->text | seqan3::views::chunk(1ULL << 42);
194+
}

0 commit comments

Comments
 (0)