Given
auto empty_line = [](auto& str){ return str.size() == 0; };
For that fact that ranges::getlines
returns an owning view_facade
that owns a buffer for its frontal iterator.
So we are kind of obligated to make that kind of range an lvalue before passing to algorithms.
auto line_range1 = ranges::getlines(std::cin);
auto iter1 = ranges::find_if_not(line_range1,empty_line);
auto input1 = std::stoi(*iter1);
And also there is a cool protection machanism preventing all dereferencing of iterators' at-time already destroyed data and make those attempt compile time errors.
So when an owning view_facade
is passed into an algorithm as rvalue, the protection engages at the dereference.
This won't compile.
auto iter2 = ranges::find_if_not(ranges::getlines(std::cin),empty_line);
// at this point the `owning` range destroyed,
// so as the buffer we (should've) hold (before!).
// So this won't compile
// auto input2 = std::stoi(*iter2);
Error as:
<source>:19:29: error: no match for 'operator*' (operand type is 'ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >')
auto input2 = std::stoi(*iter2);
^~~~~~
This also won't compile either.
// Won't compile
// auto input3 = std::stoi(*ranges::find_if_not(ranges::getlines(std::cin),
// empty_line)
// );
Error as:
<source>:22:29: error: no match for 'operator*' (operand type is 'ranges::v3::safe_iterator_t<ranges::v3::getlines_range> {aka ranges::v3::dangling<ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::getlines_range::cursor> >}')
auto input3 = std::stoi(*ranges::find_if_not(ranges::getlines(std::cin),empty_line));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
My question is that other than documentation, is there any traits or any kind of range convention to check if a range type is owning ?
Perhaps, something like constexpr bool is_owning_v(Rng&&)