I found that c++20 ranges::basic_istream_view
is slightly different from the range-v3 version.
The most important difference is that the std::ranges::basic_istream_view
does not cache its begin()
, so that each begin()
s will return the next iterator with the value that has been read (godbolt):
auto words = std::istringstream{"today is yesterday's tomorrow"};
auto view = std::ranges::istream_view<std::string>(words);
std::cout << *view.begin() << "\n"; // today
std::cout << *view.begin() << "\n"; // is
std::cout << *view.begin() << "\n"; // yesterday's
std::cout << *view.begin() << "\n"; // tomorrow
Consider the following (godbolt), If I use the range-v3 version, all the three std::ranges::find()
s will found "is"
, but if I use the std version, "is"
will be found only in the first call.
auto words = std::istringstream{"today is yesterday's tomorrow"};
auto view = std::ranges::istream_view<std::string>(words);
std::cout << *std::ranges::find(view, "is") << "\n"; // is
std::cout << *std::ranges::find(view, "is") << "\n"; // tomorrow
std::cout << *std::ranges::find(view, "is") << "\n"; // tomorrow
Why did the standard choose a different design from range-v3? Is there any potential defect if begin()
is cached?