ericniebler/range-v3

Composing ranges::view::cycle with ranges::view::slice

tremmelg opened this issue · 1 comments

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

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).