DEV Community

Pierre Gradot
Pierre Gradot

Posted on

Let's try C++20 | Erase elements in a container with std::erase()

Imagine you have a vector of integers and you want to remove all zeros. It sounds like a simple task, right? Well, before C++20, it wasn't that obvious. Let's see how C++20 makes things easier.

Before

Since the beginning of C++, there is a free function named std::remove(). Young padawans may naively use it like this:

#include <iostream> #include <vector>  int main() { std::vector data{12, 0, 654, 0, 4587, 0, 42}; for (const auto& e: data) { std::cout << e << '\t'; } std::cout << '\n'; std::remove(data.begin(), data.end(), 0); for (const auto& e: data) { std::cout << e << '\t'; } } 
Enter fullscreen mode Exit fullscreen mode

They would get this weird result:

12 0 654 0 4587 0 42 12 654 4587 42 4587 0 42 
Enter fullscreen mode Exit fullscreen mode

If we get a closer look at the description of the function on cppreference, we see:

A call to remove is typically followed by a call to a container's erase method, which erases the unspecified values and reduces the physical size of the container to match its new logical size.

Hence, the correct way to erase elements prior to C++20 is:

int main() { std::vector data{12, 0, 654, 0, 4587, 0, 42}; for (const auto& e: data) { std::cout << e << '\t'; } std::cout << '\n'; const auto logicalEnd = std::remove(data.begin(), data.end(), 0); data.erase(logicalEnd, data.end()); for (const auto& e: data) { std::cout << e << '\t'; } } 
Enter fullscreen mode Exit fullscreen mode

The result is correct this time:

12 0 654 0 4587 0 42 12 654 4587 42 
Enter fullscreen mode Exit fullscreen mode

This technique is know as the Erase–remove idiom.

Now

C++20 includes proposals P1209r0 and P1115r3. We now have free functions called std::erase() that are overloaded for the containers of the STL. They perform the remove-erase idiom.

To erase elements in a vector, you can now simply do:

#include <iostream> #include <vector>  int main() { std::vector data{12, 0, 654, 0, 4587, 0, 42}; for (const auto& e: data) { std::cout << e << '\t'; } std::cout << '\n'; const auto count = std::erase(data, 0); std::cout << count << " elements erased\n"; for (const auto& e: data) { std::cout << e << '\t'; } } 
Enter fullscreen mode Exit fullscreen mode

Much simpler, right?

Top comments (2)

Collapse
 
sandordargo profile image
Sandor Dargo

Nice, we have this finally!

Collapse
 
pgradot profile image
Pierre Gradot

Finally!