Предоставляет ли стандартная библиотека C ++ более компактную и обобщенную версию идиомы удаления-удаления?

Мы можем удалить один элемент / запись из контейнера с помощью популярной идиомы erase – remove . Однако многие из нас столкнулись бы с некоторыми проблемами при применении этой идиомы:


Есть ли у нас что-нибудь обобщенное и менее подверженное опечаткам, чем std::erase-std::remove_if или что-то вроде std::erase_if в рамках c ++ 17, или такая утилита будет в c ++ 20?


person JeJo    schedule 02.07.2019    source источник


Ответы (1)


Не входит в рамки c ++ 17, но c ++ 20 и далее!

Да. Предложение о последовательном стирании контейнеров было упомянуто в документе n4009 и, наконец, принято в Стандарт C ++ 20 как std::erase_if, который <сильный > функция, не являющаяся членом для каждого контейнера.

Это обеспечивает единую семантику стирания контейнеров для std::basic_string и всех стандартных контейнеров, кроме std::array (поскольку он имеет фиксированный размер).

Это означает, что шаблонный код

container.erase(
    std::remove_if(
        container.begin(), container.end(),
        [](const auto& element) ->bool { return /* condition */; }),
    vec.end());

просто превратится в обобщенную форму

std::erase_if(container, [](const auto& element) ->bool { return /* condition */; });

Во-вторых, этот единый синтаксис выбирает правильную семантику для каждого контейнера. Это означает


В дополнение к этому, стандарт также добавил std::erase для контейнеров последовательностей формы

std::erase(container, value_to_be_removed);
person JeJo    schedule 02.07.2019
comment
Как мне распространить это на мои собственные контейнеры? Будет ли мой собственный erase_if(...) найден ADL? - person Justin; 02.07.2019
comment
@Justin, если я правильно понял, определения erase_if(...), не являющегося членом, для собственного контейнера будет недостаточно? возможно, добавление области std:: в пространство имен std. Но в более поздней части я не уверен. - person JeJo; 02.07.2019
comment
Действительно, из бумаги, эта утилита указана для каждого стандартного контейнера и не использует ADL. Поскольку добавление пользовательской перегрузки в std не разрешено, способ настроить это для ваших собственных контейнеров будет заключаться в определении вашего собственного отдельного erase_if в вашем собственном пространстве имен, которое может пересылаться в std::erase_if или ваши собственные контейнеры '. - person Justin; 02.07.2019
comment
@Justin No ADL означает, что неквалифицированный звонок, такой как { using std::erase_if; erase_if(...); }, не поможет найти тех, кто не является членом erase_if, верно? - person Ted Lyngmo; 02.07.2019
comment
@TedLyngmo Вы можете написать это, и он найдет ваш собственный erase_if (при условии, что его можно найти с помощью ADL, например, если он определен в том же пространстве имен, что и ваш контейнер). - person Justin; 02.07.2019
comment
Зачем вы заставляете лямбды иметь возвращаемый тип bool? - person Deduplicator; 03.07.2019
comment
@ Дедупликатор Это дело вкуса. Я бы сказал. явный retin [captures] (params) - ›ret {body} (о лямбдах), неплохая практика, ИМХО. - person JeJo; 03.07.2019