¿La biblioteca estándar de C++ proporciona una versión más compacta y generalizada del lenguaje de borrado y eliminación?
c++17 c++-standard-library (1)
Podemos borrar un elemento / entrada de un contenedor mediante el popular borrado: eliminar idioma . Sin embargo, muchos de nosotros habríamos encontrado algunos problemas al aplicar este modismo:
-
Uno puede meterse fácilmente en la trampa de los errores tipográficos como
c.erase(std::remove_if(c.begin(), c.end(), pred)); // , c.end() //---> missing hereo
c.erase((std::remove_if(c.begin(), c.end(), pred), c.end())) // ^^ ^^ // extra () makes it pass only c.end() to the c.erase -
Incluso sigue la
semántica incorrecta
para los contenedores como
std::listal no seleccionar su propio miembrostd::list::remove_if()para el idioma. -
En tercer lugar, el uso de
std::remove_ifno funciona para contenedores asociativos .
¿Tenemos algo generalizado y menos propenso
a los
errores tipográficos
que
std::erase-std::remove_if
o algo como
std::erase_if
dentro del alcance de
c ++ 17
, o habrá una utilidad de este tipo en
c ++ 20
?
No en el alcance de c ++ 17 , sino de c ++ 20 en adelante.
Si
La propuesta de borrado consistente del contenedor se mencionó en el
documento n4009
y finalmente se adoptó en el
estándar C ++ 20 como
std::erase_if
que es
una función no miembro para cada contenedor
.
Esto garantiza una semántica uniforme de borrado de contenedores para
std::basic_string
y
todos los contenedores estándar
, excepto
std::array
(ya que tiene el tamaño fijo).
Esto significa que el código repetitivo
container.erase(
std::remove_if(
container.begin(), container.end(),
[](const auto& element) ->bool { return /* condition */; }),
vec.end());
simplemente se fundirá en una forma generalizada de
std::erase_if(container, [](const auto& element) ->bool { return /* condition */; });
En segundo lugar, esta sintaxis uniforme selecciona la semántica adecuada para cada contenedor . Esto significa
-
Para contenedores de secuencias como
std::vector,std::dequey parastd::std::basic_string, será equivalente acontainer.erase( std::remove_if(container.begin(), container.end(), unaryPredicate) , container.end() ); -
Para los contenedores de secuencias
std::forward_listystd::list, será equivalente acontainer.remove_if(unaryPredicate); -
Para contenedores asociativos ordenados (es decir,
std::set,std::map,std::multisetystd::multimap) y contenedores asociativos desordenados (es decir,std::unordered_set,std::unordered_map,std::unordered_multisetystd::unordered_multimap),std::erase_ifes equivalente afor (auto i = container.begin(), last = container.end(); i != last; ) { if (unaryPredicate(*i)) { i = container.erase(i); } else { ++i; } }
Además de eso, el estándar también agregó
std::erase
para los contenedores
de
secuencia
del formulario
std::erase(container, value_to_be_removed);