2015-11-04 52 views
5

刪除從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); 

等等

+0

你冷冷的時候總是寫自己的。 – NathanOliver

+2

我有! :)我只是認爲這對''很簡單,因此所有人都可以從中受益 –

+0

@SteveLorimer我也有。你專注於'list <>'嗎? – curiousguy

回答

7

此問題是由提案覆蓋3210它說:

這是添加erase_if(集裝箱,預計值)的建議,使其 更容易正確有效地消除不需要的元素。

[...]

這是令人驚訝的困難,以消除因爲區分「好」元素「壞」的元素的謂詞的容器, 不需要的元素。

STL的主要優勢之一是它的所有容器都有類似的接口 - 它們有許多共同的功能,它們遵循相同的約定。當容器接口有所不同時,其數據結構之間的根本區別是有責任的。由於STL的容器迭代器算法設計,即使這些差異通常也會被忽略。

,並指出:

正確的響應 是使用擦除remove慣用法,這是非顯而易見的,必須教導 ,而不是發現(這就是所謂的「成語」爲一個原因)。

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

頭版本(版本6.0。0)上Wandbox可用的gcc有這個標題的實現(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工作,這似乎證實了TC的建議,這也隨MSVC 2015年

+0

謝謝!你知道我在哪裏可以找到關於這些擴展的發佈時間表的信息嗎?它們是C++ 14的一部分嗎? –

+2

@SteveLorimer不,我沒有像核心工作組那樣重視圖書館工作。但是這裏[STL說可能是C++ 17](https://news.ycombinator.com/item?id=9050267)。 –