Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a trait or any convention to check if a range or a `view_facade` that owns things? (e.g. getlines)

Tags:

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));                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

godbolt.org/g/gF6nYx


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

like image 545
sandthorn Avatar asked Feb 26 '18 08:02

sandthorn


1 Answers

std::ranges::enable_borrowed_range will tell you if range type is NOT owning. See P2017R1. To implement the function you described, you could do so like this:

template <typename Rng> constexpr bool is_owning_v(Rng&&) {   return !std::ranges::enable_borrowed_range<std::remove_cvref_t<Rng>>; } 
like image 194
mmackliet Avatar answered Sep 27 '22 21:09

mmackliet