为什么标准不提供擦除删除习惯用语的便利助手?

时间:2015-11-04 13:48:01

标签: c++ stl c++17 erase-remove-idiom

从STL中的集合中删除项目需要经常使用的技术,这已成为一种习语:the erase-remove-idiom

此成语最常见的用法之一是从T

中删除vector<T>类型的项目
std::vector<Widget> widget_collection;
Widget widget;

widget_collection.erase(
    std::remove(widget_collection.begin(), widget_collection.end(), widget), 
    widget_collection.end());

这显然非常冗长,并且违反了DRY principle - 有问题的向量需要4次。

所以我的问题是为什么标准不提供方便助手?

这样的东西
widget_collection.erase_remove(widget);

std::erase_remove(widget_collection, widget);

这显然可以扩展到

widget_collection.erase_remove_if(widget, pred);

等...

1 个答案:

答案 0 :(得分:6)

提案N4009: Uniform Container Erasure涵盖了此问题,其中包含:

  

这是一个添加erase_if(container,pred)的提议   更容易正确有效地消除不需要的元素。

     

[...]

     

从容器中消除不需要的元素是非常困难的,   给出一个谓词,将“坏”元素与“好”元素区分开来。

     

STL的主要优势之一是其所有容器都具有相似性   接口 - 它们有许多共同的功能,它们也遵循相同的功能   约定。当容器接口变化时,基本区别   他们的数据结构是负责任的即使这些差异往往也是如此   由于STL的容器 - 迭代器 - 算法设计,忽略了它。

还注意到:

  

正确的回应   是使用擦除 - 删除习语,这是非显而易见的,必须教   而不是被发现(因为某种原因,它被称为“成语”)。

最新版本N4273: Uniform Container Erasure (Revision 2)看起来像adopted。它是Extensions for Library Fundamentals V2的一部分。另请参阅C++ standard libraries extensions, version 2的cppreference部分。

Wandbox上提供的gcc头版(版本6.0.0 )具有此标题的实现( 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" ;
}

此代码也适用于webcompiler,这似乎证实了T.C.的建议,这也是MSVC 2015附带的。