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

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

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

  • можно легко попасть в ловушку опечаток, таких как

    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 в рамках , или такая утилита будет в ?

4b9b3361

Ответ 1

Не в рамках , но и далее!

Да Предложение согласованного удаления контейнеров было упомянуто в статье n4009 и, наконец, принято в стандарте С++ 20 как std::erase_if который является 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);