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?

Image of AssemblyAI tool

Challenge Submission: SpeechCraft - AI-Powered Speech Analysis for Better Communication

SpeechCraft is an advanced real-time speech analytics platform that transforms spoken words into actionable insights. Using cutting-edge AI technology from AssemblyAI, it provides instant transcription while analyzing multiple dimensions of speech performance.

Read full post

Top comments (2)

Collapse
 
sandordargo profile image
Sandor Dargo

Nice, we have this finally!

Collapse
 
pgradot profile image
Pierre Gradot

Finally!

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay