I'm trying to erase a subrange returned by find_if( vec | reverse | slide(width) )
from a vector
, but I can't get their parameter types to match anyway.
I'm not sure if the iterator is invalidated in these pipes. I'd like to just use the existing subrange iterator to erase it instead of wasting performance to find it again. Is that possible?
Full code: Compiler Explorer
Core function:
std::vector<Data> take_last_successive_data(std::vector<Data> &target) {
const auto &data_is_successive = [](const auto &data) { return data.is_successive; };
auto windows = target | views::reverse | views::slide(2);
auto result = ranges::find_if(
windows,
[&](const auto &window) {
return ranges::all_of(window | views::take(window.size() - 1), data_is_successive);
}
);
if (result == windows.end()) {
std::cout << "not found\n";
return {};
} else {
// How to erase subrange `result`
target.erase();
auto ret = to_vector(*result | views::reverse);
for (const auto &data : ret) {
std::cout << data.value << ", ";
}
std::cout << '\n';
return ret;
}
}
First, decompose subrange
to get the pair of reverse_iterator
, then call its base()
to get the underlying iterator and pass it into erase()
.
Note that the erase()
must be performed after ret
is created to ensure that the iterator points to a valid element.
} else {
auto ret = to_vector(*result | views::reverse);
for (const auto &data : ret) {
std::cout << data.value << ", ";
}
std::cout << '\n';
// How to erase subrange `result`
auto [rbegin, rend] = *result;
target.erase(rend.base(), rbegin.base());
return ret;
}