为什么标准没有提供 erase-remove-idiom 的便利助手?

Why is a convenience helper for the erase-remove-idiom not provided by the standard?

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

这个习语最常见的用法之一是从 vector<T>

中删除 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);

等...

此问题已包含在提案 N4009: Uniform Container Erasure 中:

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.

还有注释:

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

最新版本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.

Wandbox 上可用的 gcc 的主要修订版(版本 6.0.0)具有此 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" ;
}

此代码也适用于 webcompiler,这似乎证实了 T.C。关于这也随 MSVC 2015 一起提供的建议。