Removing items from a collection in the STL requires a technique used so often that is has become an idiom: the erase-remove-idiom
One of the most common usages of this idiom is to remove an item of type T
from a vector<T>
std::vector<Widget> widget_collection;
Widget widget;
widget_collection.erase(
std::remove(widget_collection.begin(), widget_collection.end(), widget),
widget_collection.end());
This is obviously very verbose, and violates the DRY principle - the vector in question is required 4 times there.
So my question is why does the standard not provide a convenience helper?
Something like
widget_collection.erase_remove(widget);
or
std::erase_remove(widget_collection, widget);
This could obviously be extended to
widget_collection.erase_remove_if(widget, pred);
etc...
This issue is covered by proposal N4009: Uniform Container Erasure which says:
This is a proposal to add erase_if(container, pred), making it
easier to eliminate unwanted elements correctly and efficiently.
[...]
It's surprisingly difficult to eliminate unwanted elements from a container,
given a predicate that distinguishes "bad" elements from "good" elements.
One of the STL's major strengths is that all of its containers have similar
interfaces - they have many functions in common and they follow the same
conventions. When container interfaces vary, fundamental differences between
their data structures are responsible. Even those differences can often be
ignored, thanks to the STL's container-iterator-algorithm design.
and also notes:
The correct response
is to use the erase-remove idiom, which is non-obvious and must be taught
instead of discovered (it's called an "idiom" for a reason).
the latest version N4273: Uniform Container Erasure (Revision 2) looks like it was adopted. It is part of Extensions for Library Fundamentals V2 . Also see the cppreference section for C++ standard libraries extensions, version 2.
The head revision(version 6.0.0) of gcc available on Wandbox has an implementation of this header (see it live):
#include <experimental/vector>
#include <iostream>
int main()
{
std::vector<int> v1 = {1,2,3,4,5,6} ;
std::experimental::erase_if( v1, [] (const int &x ) { return x < 4; } ) ;
for( const auto & v : v1 )
{
std::cout << v << ", " ;
}
std::cout << "\n" ;
}
This code also work on webcompiler which seems to confirm T.C.'s suggestion that this also shipped with MSVC 2015.