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

Ste*_*mer 4 c++ stl erase-remove-idiom c++17

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

这个成语最常见的用法之一是T从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());
Run Code Online (Sandbox Code Playgroud)

这显然非常冗长,违反了DRY原则 - 有问题的载体需要4次.

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

就像是

widget_collection.erase_remove(widget);
Run Code Online (Sandbox Code Playgroud)

要么

std::erase_remove(widget_collection, widget);
Run Code Online (Sandbox Code Playgroud)

这显然可以扩展到

widget_collection.erase_remove_if(widget, pred);
Run Code Online (Sandbox Code Playgroud)

等等...

Sha*_*our 6

N4009提案涵盖了这个问题:统一容器擦除说:

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

[...]

考虑到将"坏"元素与"好"元素区分开来的谓词,从容器中消除不需要的元素是非常困难的.

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

并且还注意到:

正确的反应是使用擦除 - 移除习语,这是非显而易见的,必须教导而不是被发现(因为某种原因,它被称为"习语").

最新版本N4273:Uniform Container Erasure(修订版2)看起来像是被采用了.它是Extensions for 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" ;
}
Run Code Online (Sandbox Code Playgroud)

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

  • @SteveLorimer不,我没有像核心工作组那样关注图书馆的工作.但是这里[STL说可能是C++ 17](https://news.ycombinator.com/item?id=9050267)的提议. (2认同)