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!