Namespaces
Variants

std::remove, std::remove_if

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p. ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de modificación de secuencia
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Operaciones de ordenación y relacionadas
Operaciones de partición
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de mezcla (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
Definido en el encabezado <algorithm>
template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
(1) (hasta C++26)
(constexpr desde C++20)
template< class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type >
constexpr ForwardIt remove( ForwardIt first, ForwardIt last,
                            const T& value );
(desde C++26)
template< class ExecutionPolicy, class ForwardIt, class T >
ForwardIt remove( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last, const T& value );
(2) (desde C++17)
(hasta C++26)
template< class ExecutionPolicy, class ForwardIt,
          class T = typename std::iterator_traits
                        <ForwardIt>::value_type >
ForwardIt remove( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last, const T& value );
(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,
                     ForwardIt first, ForwardIt last, UnaryPred p );
(4) (desde C++17)

Elimina todos los elementos que satisfacen criterios específicos del rango [first, last) y devuelve un iterador más allá del final para el nuevo final del rango.

1) Elimina todos los elementos que son iguales a value (usando operator==).
3) Elimina todos los elementos para los cuales el predicado p devuelve true.
2,4) Igual que (1,3), pero ejecutado de acuerdo con policy.
Estas sobrecargas participan en la resolución de sobrecarga solo si el valor de la siguiente expresión es true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(hasta C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(desde C++20)


Si el tipo de valor de ForwardIt no es CopyAssignable, el comportamiento no está definido.

(hasta C++11)

Si el tipo de *first no es MoveAssignable, el comportamiento no está definido.

(desde C++11)

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:
  • Cada elemento de [ result , last ) tiene un estado válido pero no especificado, porque la asignación de movimiento puede eliminar elementos moviendo desde elementos que originalmente estaban en ese rango.
(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 v de tipo (posiblemente const) VT , donde VT es el tipo de valor de ForwardIt , independientemente de la categoría de valor , y no debe modificar v . Por lo tanto, no se permite un tipo de parámetro VT & , ni tampoco VT a menos que para VT un movimiento sea equivalente a una copia (since C++11) . ​

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 ) :

1,2) Exactamente N comparaciones utilizando operator == .
3,4) Exactamente N aplicaciones del predicado p .

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 ExecutionPolicy es uno de los standard policies , std::terminate es llamado. Para cualquier otro ExecutionPolicy , 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 satisfacen criterios específicos
(plantilla de función & objeto de función de algoritmo)
elimina elementos duplicados consecutivos en un rango
(plantilla de función & objeto de función de algoritmo)
elimina elementos que satisfacen criterios específicos
(objeto de función de algoritmo)