Удаление элементов из коллекции в STL требует такой часто используемой техники, которая стала идиомой: стирание-удаление-идиома
Одним из наиболее распространенных способов использования этой идиомы является удаление элемента типа 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());
Это, очевидно, очень многословно, и нарушает СУХОЙ принцип — рассматриваемый вектор требуется 4 раза.
Итак, мой вопрос: почему стандарт не предоставляет вспомогательный инструмент?
Что-то вроде
widget_collection.erase_remove(widget);
или же
std::erase_remove(widget_collection, widget);
Это, очевидно, может быть распространено на
widget_collection.erase_remove_if(widget, pred);
так далее…
Эта проблема покрыта предложением N4009: равномерное стирание контейнера который говорит:
Это предложение добавить erase_if (container, pred), сделав его
[…]
легче устранить ненужные элементы правильно и эффективно.Удивительно трудно удалить ненужные элементы из контейнера,
дан предикат, который отличает «плохие» элементы от «хороших» элементов.Одной из основных сильных сторон STL является то, что все ее контейнеры имеют одинаковый
интерфейсы — у них много общих функций, и они следуют одному и тому же
конвенций. Когда контейнерные интерфейсы различаются, фундаментальные различия между
их структуры данных несут ответственность. Даже эти различия часто могут быть
игнорируется, благодаря дизайну алгоритма контейнера-итератора STL.
а также отмечает:
Правильный ответ
заключается в использовании идиомы стирания-удаления, которая неочевидна и должна преподаваться
вместо того, чтобы обнаружить (это называется «идиома» по причине).
Последняя версия N4273: равномерное стирание контейнера (редакция 2) похоже это было принят. Это часть Расширения для библиотечных основ V2 . Также см. Раздел cppreference для Стандартные библиотеки C ++, версия 2.
Головная ревизия (версия 6.0.0) gcc, доступный на Wandbox, имеет реализацию этого заголовка (увидеть это в прямом эфире):
#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.
Других решений пока нет …