4

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...

4

1 回答 1

6

提案N4009:Uniform Container Erasure涵盖了这个问题,其中说:

这是一个添加 erase_if(container, pred) 的建议,可以更轻松地正确有效地消除不需要的元素。

[...]

考虑到区分“坏”元素和“好”元素的谓词,从容器中消除不需要的元素非常困难。

STL 的主要优势之一是它的所有容器都具有相似的接口——它们具有许多共同的功能并且它们遵循相同的约定。当容器接口变化时,它们的数据结构之间的根本差异是负责任的。由于 STL 的容器迭代器算法设计,即使是这些差异也经常可以忽略。

并注意:

正确的反应是使用擦除删除成语,这是不明显的,必须教而不是发现(它被称为“成语”是有原因的)。

最新版本N4273: Uniform Container Erasure (Revision 2)貌似被采纳了它是Library Fundamentals V2 扩展的一部分。另请参阅C++ 标准库扩展版本 2的 cppreference 部分。

Wandbox 上可用的 gcc的头部修订版(6.0.0 版)具有此头部的实现(现场查看):

#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" ;
}

此代码也适用于webcompiler,这似乎证实了 TC 的建议,即 MSVC 2015 也附带了此代码。

于 2015-11-04T14:02:05.803 回答