Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++23: How to erase a subrange from vector

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;
    }
}
like image 942
Sprite Avatar asked Oct 20 '25 00:10

Sprite


1 Answers

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;
}

Demo

like image 85
康桓瑋 Avatar answered Oct 22 '25 13:10

康桓瑋