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
std::erase_if(container, pred)removes every element for whichpredreturnstrue, keeps the rest in their original order, and returns how many it removed.std::erase(container, value)removes every element equal tovalue.- Both work on
vector,string,dequeandlist, anderase_ifalso works on maps and sets.
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.