¿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 here
o
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::list
al no seleccionar su propio miembrostd::list::remove_if()
para el idioma. -
En tercer lugar, el uso de
std::remove_if
no 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::deque
y 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_list
ystd::list
, será equivalente acontainer.remove_if(unaryPredicate);
-
Para contenedores asociativos ordenados (es decir,
std::set
,std::map
,std::multiset
ystd::multimap
) y contenedores asociativos desordenados (es decir,std::unordered_set
,std::unordered_map
,std::unordered_multiset
ystd::unordered_multimap
),std::erase_if
es 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);