std::remove, std::remove_if
Definido en el archivo de encabezado <algorithm>
|
||
(1) | ||
template< class ForwardIt, class T > ForwardIt remove( ForwardIt first, ForwardIt last, const T& value ); |
(constexpr desde C++20) (hasta C++26) |
|
template< class ForwardIt, class T = typename std::iterator_traits <ForwardIt>::value_type > |
(desde C++26) | |
(2) | ||
template< class ExecutionPolicy, class ForwardIt, class T > ForwardIt remove( ExecutionPolicy&& policy, |
(desde C++17) (hasta C++26) |
|
template< class ExecutionPolicy, class ForwardIt, class T = typename std::iterator_traits |
(desde C++26) | |
template< class ForwardIt, class UnaryPred > ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPred p ); |
(3) | (constexpr desde C++20) |
template< class ExecutionPolicy, class ForwardIt, class UnaryPred > ForwardIt remove_if( ExecutionPolicy&& policy, |
(4) | (desde C++17) |
Elimina todos los elementos que satisfacen un criterio específico del rango [
first,
last)
y devuelve un iterador pasado el final para el nuevo final del rango.
Si el tipo valor de |
(hasta C++11) |
Si el tipo de *first no es AsignablePorMovimiento, el comportamiento no está definido. |
(desde C++11) |
Contenido |
[editar] Explicación
La eliminación se realiza desplazando los elementos del rango de forma que los elementos que no se van a eliminar aparezcan al principio del rango.
- El desplazamiento se realiza mediante la asignación de copia (hasta C++11)asignación de movimiento (desde C++11).
- La operación de eliminación es estable: el orden relativo de los elementos que no se eliminarán permanece igual.
- La secuencia subyacente de
[
first,
last)
no se acorta mediante la operación de eliminación. Dado result como el iterador devuelto:
- Todos los iteradores en
[
result,
last)
siguen siendo desreferenciables.
- Todos los iteradores en
|
(desde C++11) |
[editar] Parámetros
first, last | - | El rango de elementos a procesar. |
value | - | El valor de los elementos a eliminar. |
policy | - | La política de ejecución a usar. Véase política de ejecución para más detalles. |
p | - | Predicado unario que devuelve true Si el elemento debe ser eliminado.. La expresión p(v) debe ser convertible a bool para cada argumento |
Requisitos de tipo | ||
-ForwardIt debe satisfacer los requisitos de ForwardIterator.
| ||
-UnaryPredicate debe satisfacer los requisitos de Predicado.
|
[editar] Valor de retorno
Iterador pasado del final para el nuevo rango de valores (si éste no es end, entonces apunta a un valor no especificado, al igual que los iteradores a cualquier valor entre este iterador y end).
[editar] Complejidad
Dada N como std::distance(first, last):
[editar] Excepciones
Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy
(política de ejecución) reportan errores tales que:
- Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y la política de ejecución es una de las tres políticas estándar, se llama a std::terminate. Para cualquier otra política de ejecución, el comportamiento está definido por la implementación.
- Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.
[editar] Posible implementación
remove (1) |
---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> ForwardIt remove(ForwardIt first, ForwardIt last, const T& value) { first = std::find(first, last, value); if (first != last) for (ForwardIt i = first; ++i != last;) if (!(*i == value)) *first++ = std::move(*i); return first; } |
remove_if (3) |
template<class ForwardIt, class UnaryPred> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p) { first = std::find_if(first, last, p); if (first != last) for (ForwardIt i = first; ++i != last;) if (!p(*i)) *first++ = std::move(*i); return first; } |
[editar] Notas
Una llamada a remove
suele ir seguida de una llamada a la función miembro erase
de un contenedor para eliminar elementos del contenedor. Estas dos invocaciones juntas constituyen lo que se denomina el modismo borrar-eliminar.
El mismo efecto también se puede lograr con las siguientes funciones no miembro:
|
(desde C++20) |
Las funciones miembro de nombre similar, de los contenedores list::remove, list::remove_if, forward_list::remove y forward_list::remove_if borran los elementos eliminados.
Estos algoritmos no se pueden utilizar con contenedores asociativos como std::set y std::map porque sus tipos de iterador no hacen desreferencia a los tipos AsignablePorMovimiento (las claves en estos contenedores no son modificables).
La biblioteca estándar también define una sobrecarga de std::remove en <cstdio>, que toma un const char* y se utiliza para eliminar archivos.
Debido a que std::remove
toma value por referencia, puede tener un comportamiento no esperado si es una referencia a un elemento del rango [
first,
last)
.
Macro de Prueba de característica | Valor | Estándar | Comentario |
---|---|---|---|
__cpp_lib_algorithm_default_value_type |
202403 | (C++26) | inicialización por lista para los algoritmos (1,2) |
[editar] Ejemplo
El siguiente código elimina todos los espacios de una cadena desplazando todos los caracteres que no son espacios a la izquierda y luego borrando el extra. Esto es un ejemplo del modismo borrar-eliminar.
#include <algorithm> #include <cassert> #include <cctype> #include <complex> #include <iostream> #include <string> #include <string_view> #include <vector> int main() { std::string str1 {"Texto con algunos espacios"}; auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' '); // Los espacios se eliminan de la cadena solo lógicamente. // Usamos una vista sobre cadena, la cadena original aún no se ha reducido: std::cout << std::string_view(str1.begin(), noSpaceEnd) << " tamaño: " << str1.size() << '\n'; str1.erase(noSpaceEnd, str1.end()); // Los espacios se eliminan de la cadena físicamente. std::cout << str1 << " tamaño: " << str1.size() << '\n'; std::string str2 = "Texto\n con\talgunos \t espacios en blanco\n\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x) { return std::isspace(x); }), str2.end()); std::cout << str2 << '\n'; std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}}; #ifdef __cpp_lib_algorithm_default_value_type nums.erase(std::remove(nums.begin(), nums.end(), {1, 3}), nums.end()); #else nums.erase(std::remove(nums.begin(), nums.end(), std::complex<double>{1, 3}), nums.end()); #endif assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}})); }
Salida:
Textoconalgunosespacios tamaño: 28 Textoconalgunosespacios tamaño: 23 Textoconalgunosespaciosenblanco
[editar] Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
---|---|---|---|
LWG 283 | C++98 | Se requería que T fuera ComparableEnIgualdad, peroel tipo valor de ForwardIt no siempre es T .
|
Se requiere que el tipo valor de ForwardIt en su lugar sea AsignablePorCopia. |
[editar] Véase también
Copia un rango de elementos omitiendo los que satisfacen un criterio específico (plantilla de función) | |
Elimina elementos duplicados consecutivos en un rango. (plantilla de función) | |
(C++20)(C++20) |
Elimina elementos que satisfacen un criterio específico. (niebloid) |