DEV Community

Pierre Gradot
Pierre Gradot

Posted on

5 2

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?

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (2)

Collapse
 
sandordargo profile image
Sandor Dargo

Nice, we have this finally!

Collapse
 
pgradot profile image
Pierre Gradot

Finally!

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more