The erase-remove pattern compacts unwanted values and then trims the container to the new logical end.

remove_if `std::remove_if` moves kept values forward and returns the new logical end.
erase `erase` removes the leftover tail after `remove_if` has compacted the kept values.

Remove Erase

keepAtLeast
remove_erase.cpp
Replay: real traced execution (multi-file project)
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> levels{3, 7, 2, 9, 5};
    int keepAtLeast = 5;

    auto newEnd = std::remove_if(levels.begin(), levels.end(),
        [keepAtLeast](int level) {
            return level < keepAtLeast;
        });
    levels.erase(newEnd, levels.end());

    std::cout << "keepAtLeast=" << keepAtLeast << std::endl;
    std::cout << "kept=" << levels.size() << std::endl;
    std::cout << "first=" << levels.front() << std::endl;
    return 0;
}
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> levels{3, 7, 2, 9, 5};
    int keepAtLeast = 3;

    auto newEnd = std::remove_if(levels.begin(), levels.end(),
        [keepAtLeast](int level) {
            return level < keepAtLeast;
        });
    levels.erase(newEnd, levels.end());

    std::cout << "keepAtLeast=" << keepAtLeast << std::endl;
    std::cout << "kept=" << levels.size() << std::endl;
    std::cout << "first=" << levels.front() << std::endl;
    return 0;
}
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> levels{3, 7, 2, 9, 5};
    int keepAtLeast = 8;

    auto newEnd = std::remove_if(levels.begin(), levels.end(),
        [keepAtLeast](int level) {
            return level < keepAtLeast;
        });
    levels.erase(newEnd, levels.end());

    std::cout << "keepAtLeast=" << keepAtLeast << std::endl;
    std::cout << "kept=" << levels.size() << std::endl;
    std::cout << "first=" << levels.front() << std::endl;
    return 0;
}
  1. levels ← [3, 7, 2, 9, 5], keepAtLeast ← 5, newEnd ← (empty)

    5int main() {6    std::vector<int> levels→ [3, 7, 2, 9, 5]{3, 7, 2, 9, 5};7    int keepAtLeast→ 5 = 5; //@keepAtLeast=3, 889    auto newEnd→ (empty) = std::remove_if(levels→ [7, 9, 5, 9, 5].begin(), levels.end(),10        [keepAtLeast](int level) {11            return level < keepAtLeast;12        });13    levels→ [7, 9, 5].erase(newEnd(empty), levels.end());1415    std::cout << "keepAtLeast=" << keepAtLeast5 << std::endl;16    std::cout << "kept=" << levels[7, 9, 5].size() << std::endl;17    std::cout << "first=" << levels[7, 9, 5].front() << std::endl;18    return 0;19}
    outputkeepAtLeast=5
    kept=3
    first=7
  1. levels ← [3, 7, 2, 9, 5], keepAtLeast ← 3, newEnd ← (empty)

    5int main() {6    std::vector<int> levels→ [3, 7, 2, 9, 5]{3, 7, 2, 9, 5};7    int keepAtLeast→ 3 = 3;89    auto newEnd→ (empty) = std::remove_if(levels→ [3, 7, 9, 5, 5].begin(), levels.end(),10        [keepAtLeast](int level) {11            return level < keepAtLeast;12        });13    levels→ [3, 7, 9, 5].erase(newEnd(empty), levels.end());1415    std::cout << "keepAtLeast=" << keepAtLeast3 << std::endl;16    std::cout << "kept=" << levels[3, 7, 9, 5].size() << std::endl;17    std::cout << "first=" << levels[3, 7, 9, 5].front() << std::endl;18    return 0;19}
    outputkeepAtLeast=3
    kept=4
    first=3
  1. levels ← [3, 7, 2, 9, 5], keepAtLeast ← 8, newEnd ← (empty)

    5int main() {6    std::vector<int> levels→ [3, 7, 2, 9, 5]{3, 7, 2, 9, 5};7    int keepAtLeast→ 8 = 8;89    auto newEnd→ (empty) = std::remove_if(levels→ [9, 7, 2, 9, 5].begin(), levels.end(),10        [keepAtLeast](int level) {11            return level < keepAtLeast;12        });13    levels→ [9].erase(newEnd(empty), levels.end());1415    std::cout << "keepAtLeast=" << keepAtLeast8 << std::endl;16    std::cout << "kept=" << levels[9].size() << std::endl;17    std::cout << "first=" << levels[9].front() << std::endl;18    return 0;19}
    outputkeepAtLeast=8
    kept=1
    first=9