ericniebler / range-v3

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

iter_move for views that cycle #1617

Open roibarkan opened 3 years ago

roibarkan commented 3 years ago

Hi, Wanted to ask how iter_move should be implemented for views that go over an underlying iterator more than once. The following code tries to duplicate and move 5 instances of the same object into a vector, and fails.

#include <iostream>
#include <range/v3/all.hpp>  // get everything
#include <string>

int main() {
  std::string s{"hello"};
  auto strings = ranges::views::single(s) | ranges::views::cycle |
                 ranges::views::take(5) | 
                 ranges::views::move | ranges::to_vector;
  ranges::for_each(strings, [](const auto& c) { std::cout << c << ' '; });
  std::cout << "\nPrinted " << ranges::size(strings) << " strings.\n";
}

Because the range that we're moving into the vector has length 5, but only a single underlying string - this doesn't work as expected. https://godbolt.org/z/rqfvPf38q

Note that if we replace ranges::views::single(s) with ranges::views::repeat_n(s,1) things will work as expected - I'm not sure why.

So - It seems to me that the proper fix has to do with iter_move for ranges::views::cycle - but perhaps it is more related to ranges::views::single ? Perhaps this is all by design and one isn't supposed to move out of such a filter chain ?

I'll be happy to know what experts think. Thanks,

ericniebler commented 3 years ago

This seems like a bug. You shouldn't be able to move out of a cyclic range.