Title
Allow ranges to be conditionally borrowed
Status
ready
Section
[range.reverse][range.take][range.drop] [range.drop.while][range.common][range.drop.while] [range.elements]
Submitter
Barry Revzin

Created on 2020-11-01.00:00:00 last changed 1 week ago

Messages

Date: 2020-11-01.18:43:31
Resolved by

Rationale:

P2017R1.
Date: 2020-11-01.19:09:34

Consider the following approach to trimming a std::string:

auto trim(std::string const& s) {
  auto isalpha = [](unsigned char c){ return std::isalpha(c); };
  auto b = ranges::find_if(s, isalpha);
  auto e = ranges::find_if(s | views::reverse, isalpha).base();
  return subrange(b, e);
}

This is a fairly nice and, importantly, safe way to implement trim. The iterators b and e returned from find_if will not dangle, since they point into the string s whose lifetime outlives the function. But the status quo in C++20 is that s | views::reverse is not a borrowed range (because reverse_view<V> is never a borrowed range for any V). As a result, find_if(s | views::reverse, isalpha) returns dangling rather than a real iterator.

Instead, you have to write it this way, introducing a new named variable for the reversed view:

auto trim(std::string const& s) {
  auto isalpha = [](unsigned char c){ return std::isalpha(c); };
  auto b = ranges::find_if(s, isalpha);
  auto reversed = s | views::reverse;
  auto e = ranges::find_if(reversed, isalpha).base();
  return subrange(b, e);
}

But borrowed range can be a transitive property. s itself is a borrowed range (as all lvalue references are) so s | views::reverse could be made to be too, which would allow the first example above to work with really no downside. We know such an iterator would not dangle, we just need to teach the library this.

P2017R1 resolves this by making reverse_view<V> a borrowed range when V is a borrowed range (and likewise several other range adapters).

History
Date User Action Args
2021-01-15 22:07:14adminsetstatus: new -> ready
2020-11-01 18:43:31adminsetmessages: + msg11528
2020-11-01 00:00:00admincreate