C/C++ Arena

Step 6 of 6

Erase with a condition

Removing every element that matches a condition sounds simple, but erasing inside a loop is a known trap: after v.erase(it), the iterator it is invalid, and indexes shift under you. The standard library solves it properly.

C++20 gives you a single call:

#include <iostream>
#include <string>
#include <vector>

struct Task {
    std::string title;
    bool done;
};

int main() {
    std::vector<int> v = {5, -2, 8, -1, 0, 3};
    auto removed = std::erase_if(v, [](int x) { return x < 0; });
    for (int x : v) std::cout << x << " ";
    std::cout << "(removed " << removed << ")\n";

    std::vector<Task> tasks = {{"shop", true}, {"code", false}, {"sleep", true}};
    std::erase_if(tasks, [](const Task& t) { return t.done; });
    for (const auto& t : tasks) std::cout << t.title << "\n";

    std::string s = "b-a-n-a-n-a";
    std::erase(s, '-');                      // remove a specific value
    std::cout << s << "\n";
}
5 8 0 3 (removed 2)
code
banana

How it works

The old way: erase-remove

Before C++20 you'd see this idiom everywhere, and you'll still meet it in existing code:

v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());

std::remove_if doesn't actually shrink the vector (an algorithm only sees iterators, not the container). It moves the elements to keep to the front and returns an iterator to the new logical end. v.erase(that, v.end()) then chops off the leftovers. Forgetting the erase part is a classic bug: the size never changes.

Predicates on pairs

Your vector holds std::pair<std::string, int>, so the lambda takes const std::pair<std::string, int>& p (or const auto& p) and looks at p.second. Read the condition carefully: "0 or less" means <= 0.

Your task

Write void drop_dead(std::vector<std::pair<std::string, int>>& players) that removes players whose hp (the int) is 0 or less.

Challenge 2

Write int remove_short(std::vector<std::string>& words, std::size_t min_len) that removes every word shorter than min_len and returns how many were removed. Use std::erase_if.

Challenge 3

Write int remove_duplicates(std::vector<int>& v) that removes every value that already appeared earlier, keeping the first copy and the original order, and returns how many were removed. Use std::erase_if with a lambda that captures a std::set<int> of seen values by reference.

Previous: Captures