std:: remove, std:: remove_if
|
Definido en el 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 cumplen un criterio específico del rango
[
first
,
last
)
y retorna un iterador más allá del nuevo final del rango.
|
std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> es true . |
(hasta C++20) |
|
std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> es true . |
(desde C++20) |
|
Si el
tipo de valor
de
|
(hasta C++11) |
|
Si el tipo de * first no es MoveAssignable , el comportamiento no está definido. |
(desde C++11) |
Contenidos |
Explicación
La eliminación se realiza desplazando los elementos en el rango de tal manera que los elementos que no se deben eliminar aparezcan al principio del rango.
- El desplazamiento se realiza mediante copy assignment (until C++11) move assignment (since C++11) .
- La operación de eliminación es estable: el orden relativo de los elementos que no se eliminan 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 dereferenceable .
-
Todos los iteradores en
|
(desde C++11) |
Parámetros
| first, last | - | el par de iteradores que define el rango de elementos a procesar |
| value | - | el valor de los elementos a eliminar |
| policy | - | la política de ejecución a utilizar |
| p | - |
predicado unario que retorna
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 cumplir con los requisitos de
LegacyForwardIterator
.
|
||
-
UnaryPredicate
debe cumplir con los requisitos de
Predicate
.
|
||
Valor de retorno
Iterador pasado por el final para el nuevo rango de valores (si este no es end , entonces apunta a un valor no especificado, y lo mismo hacen los iteradores hacia cualquier valor entre este iterador y end ).
Complejidad
Dado N como std:: distance ( first, last ) :
Excepciones
Las sobrecargas con un parámetro de plantilla llamado
ExecutionPolicy
reportan errores de la siguiente manera:
-
Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y
ExecutionPolicyes uno de los standard policies , std::terminate es llamado. Para cualquier otroExecutionPolicy, el comportamiento está definido por la implementación. - Si el algoritmo falla al asignar memoria, std::bad_alloc es lanzado.
Implementación posible
| 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; } |
Notas
Una llamada a
remove
normalmente es seguida por una llamada a la función miembro
erase
del contenedor para eliminar realmente los elementos del contenedor. Estas dos invocaciones juntas constituyen el denominado
erase-remove idiom
.
|
El mismo efecto también puede lograrse mediante las siguientes funciones no miembro:
|
(desde C++20) |
Las funciones miembro de contenedores con nombres similares member functions list::remove , list::remove_if , forward_list::remove , y forward_list::remove_if eliminan los elementos removidos.
Estos algoritmos no pueden utilizarse con contenedores asociativos como std::set y std::map porque sus tipos de iterador no se desreferencian a tipos MoveAssignable (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 el
value
por referencia, puede tener un comportamiento inesperado si es una referencia a un elemento del rango
[
first
,
last
)
.
| Macro de prueba de características | Valor | Std | Característica |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | Inicialización de lista para algoritmos ( 1,2 ) |
Ejemplo
El siguiente código elimina todos los espacios de una cadena desplazando todos los caracteres que no son espacios hacia la izquierda y luego borrando los sobrantes. Este es un ejemplo del erase-remove idiom .
#include <algorithm> #include <cassert> #include <cctype> #include <complex> #include <iomanip> #include <iostream> #include <string> #include <string_view> #include <vector> int main() { std::string str1{"Quick Red Dog"}; std::cout << "1) " << std::quoted(str1) << '\n'; const auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' '); std::cout << "2) " << std::quoted(str1) << '\n'; // The spaces are removed from the string only logically. // Note, we use view, the original string is still not shrunk: std::cout << "3) " << std::quoted(std::string_view(str1.begin(), noSpaceEnd)) << ", size: " << str1.size() << '\n'; str1.erase(noSpaceEnd, str1.end()); // The spaces are removed from the string physically. std::cout << "4) " << std::quoted(str1) << ", size: " << str1.size() << '\n'; std::string str2 = "Jumped\n Over\tA\vLazy \t Fox\r\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x) { return std::isspace(x); }), str2.end()); std::cout << "5) " << std::quoted(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:
1) "Quick Red Dog" 2) "QuickRedDog Dog" 3) "QuickRedDog", size: 15 4) "QuickRedDog", size: 11 5) "JumpedOverALazyFox"
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 283 | C++98 |
T
se requería que fuera
EqualityComparable
, pero
el tipo de valor de
ForwardIt
no siempre es
T
|
se requiere que el tipo de valor de
ForwardIt
sea CopyAssignable en su lugar |
Véase también
|
copia un rango de elementos omitiendo aquellos que cumplen criterios específicos
(plantilla de función) |
|
|
elimina elementos duplicados consecutivos en un rango
(plantilla de función) |
|
|
(C++20)
(C++20)
|
elimina elementos que cumplen criterios específicos
(objeto función de algoritmo) |