Daily bit(e) C++. std::erase, std::erase_if
Daily bit(e) C++ #215. набор перегрузок, специфичный для контейнеров C++20, для стирания элементов по значению или по предикату: std::erase
и std::erase_if
.
До C++20 удаление элементов из большинства контейнеров на основе их значений или предикатов было двухэтапным процессом.
В C++20 был добавлен набор перегрузок функций, специфичный для контейнеров, std::erase
и std::erase_if
. Эти функции упрощают двухэтапный процесс до одного вызова и (для версии на основе значения) поддерживают гетерогенные сравнения.
#include <vector>
#include <map>
#include <algorithm>
std::vector<int> data{1,2,3,4,5};
std::erase(data, 3);
// то же самое, что и:
auto it = std::remove(data.begin(), data.end(), 3);
data.erase(it, data.end());
// data == {1, 2, 4, 5}
std::erase_if(data, [](int v) { return v % 2 == 0; });
// то же самое, что и:
it = std::remove_if(data.begin(), data.end(),
[](int v) { return v % 2 == 0; });
data.erase(it, data.end());
// Дополнительно std::erase(_if) возвращает
// количество удаленных элементов:
size_t cnt = std::erase_if(data, [](int v){ return v != 0; });
// cnt == 2, data == {}
// Поддерживается для:
// std::vector, std::deque, std::list,
// std::forward_list, std::string
// Гетерогенное сравнение:
std::vector<std::string> mixed{"hello","this","is","dog"};
std::erase(mixed, "hello");
// "hello" напрямую сравнивается
// с каждым элементом без преобразования
// mixed == {"this", "is", "dog"}
// неупорядоченные и ассоциативные контейнеры
// поддерживают только std::erase_if
std::map<int,int> map{{1,2},{2,3},{3,4}};
std::erase_if(map, [](auto &e) { return e.first < 3; });
// map == {3->4}
// Обратите внимание, что map::erase() уже
// поддерживает гетерогенное удаление-по-значению
Открыть пример на Compiler Explorer.