ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.12k stars 440 forks source link

Composing ranges::view::cycle with ranges::view::slice #778

Closed tremmelg closed 6 years ago

tremmelg commented 6 years ago

Composing ranges::view::cycle with ranges::view::slice results in a view that returns begin and endpoints that compare equal. On the other hand, ranges::distance returns the expected 512. Also, see the example below.

#include <iostream>
#include <iterator>
#include <vector>

#include <range/v3/all.hpp>

int main() {
  const auto length = 512;
  const auto k = 16;

  std::vector<int> input(length);

  auto output = ranges::view::cycle(input)
              | ranges::view::slice(length + k, 2 * length + k);

  if (ranges::begin(output) == ranges::end(output)) {
    std::cout << "End equals begin!\n";
    std::cout << "Size: " << std::size(output) << "\n";
    std::cout << "Distance: " << ranges::distance(output) << "\n";
    return 1;
  }
}

Compiling the above example against 2ff4cf2 and running it gives:

% ./cycle_slice
End equals begin!
Size: 512
Distance: 512
CaseyCarter commented 6 years ago

The bug here is that view::slice incorrectly believes that the bounded range [it, it + count) is equivalent to the counted range [it, count) when it is a RandomAccessIterator (See https://github.com/ericniebler/range-v3/blob/master/include/range/v3/view/slice.hpp#L142). I suggest replacing view::slice(first, last) with view::drop(first) | view::take(last - first) as a workaround until we get this fixed (a la https://wandbox.org/permlink/TbXQsmx0YfvQcRKj).