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

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

  • можно легко попасть в ловушку опечаток вроде

    c.erase(std::remove_if(c.begin(), c.end(), pred));
    //                                             , c.end() //---> missing here
    

    или

    c.erase((std::remove_if(c.begin(), c.end(), pred), c.end()))
    //      ^^                                               ^^
    // extra () makes it pass only c.end() to the c.erase
    
  • Это даже следует неправильной семантике для таких контейнеров, как std::list не выбрав своего члена std::list::remove_if() для идиомы.
  • В-третьих, использование std::remove_if не работает для ассоциативных контейнеры .

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

1 Ответ

26 голосов
/ 02 июля 2019

Не входит в область действия , но и далее!

Да .Предложение о последовательном удалении контейнеров было упомянуто в 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);
...