Namespaces
Variants

std::ranges::remove, std::ranges::remove_if

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos en rangos (C++20)
Algoritmos restringidos, 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)

Ordenación y operaciones 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 fusión (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


 
Algoritmos restringidos
Todos los nombres en este menú pertenecen al espacio de nombres std::ranges
Operaciones de secuencia no modificadoras
Operaciones de modificación de secuencia
Operaciones de partición
Operaciones de ordenación
Operaciones de búsqueda binaria (en rangos ordenados)
       
       
Operaciones de conjunto (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
       
       
Operaciones de permutación
Operaciones de pliegue
Operaciones sobre almacenamiento no inicializado
Tipos de retorno
 
Definido en el encabezado <algorithm>
Firma de llamada
template< std::permutable I, std::sentinel_for<I> S,
          class T, class Proj = std::identity >
requires std::indirect_binary_predicate
             <ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>
    remove( I first, S last, const T& value, Proj proj = {} );
(1) (desde C++20)
(hasta C++26)
template< std::permutable I, std::sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj> >
requires std::indirect_binary_predicate
             <ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>
    remove( I first, S last, const T& value, Proj proj = {} );
(desde C++26)
template< ranges::forward_range R,
          class T, class Proj = std::identity >
requires std::permutable<ranges::iterator_t<R>> &&
         std::indirect_binary_predicate
             <ranges::equal_to,
              std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_subrange_t<R>
    remove( R&& r, const T& value, Proj proj = {} );
(2) (desde C++20)
(hasta C++26)
template< ranges::forward_range R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::iterator_t<R>, Proj> >
requires std::permutable<ranges::iterator_t<R>> &&
         std::indirect_binary_predicate
             <ranges::equal_to,
              std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_subrange_t<R>
    remove( R&& r, const T& value, Proj proj = {} );
(desde C++26)
template< std::permutable I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr ranges::subrange<I>
    remove_if( I first, S last, Pred pred, Proj proj = {} );
(3) (desde C++20)
template< ranges::forward_range R,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>
    remove_if( R&& r, Pred pred, Proj proj = {} );
(4) (desde C++20)

Elimina todos los elementos que satisfacen criterios específicos del rango [first, last) y devuelve un subrango [ret, last), donde ret es un iterador pasado el final para el nuevo final del rango.

1) Elimina todos los elementos que son iguales a value, usando std::invoke(proj, *i) == value para comparar.
3) Elimina todos los elementos para los cuales std::invoke(pred, std::invoke(proj, *i)) devuelve true.
2,4) Igual que (1,3), pero utiliza r como rango, como si usase ranges::begin(r) como first y ranges::end(r) como last.

La eliminación se realiza desplazando (mediante asignación de movimiento) los elementos en el rango de tal manera que los elementos que no deben eliminarse aparecen al principio del rango. El orden relativo de los elementos que permanecen se conserva y el tamaño físico del contenedor no cambia. Los iteradores que apuntan a un elemento entre el nuevo final lógico y el final físico del rango aún se pueden desreferenciar, pero los elementos mismos tienen valores no especificados (según la postcondición de MoveAssignable).

Las entidades similares a funciones descritas en esta página son objetos función de algoritmo (conocidos informalmente como niebloids), es decir:

Parámetros

first, last - el par iterador-centinela que define el rango de elementos a procesar
r - el rango de elementos a procesar
value - el valor de los elementos a eliminar
pred - predicado a aplicar a los elementos proyectados
proj - proyección a aplicar a los elementos

Valor de retorno

{ ret, last } , donde [ first , ret ) es el subrango resultante después de la eliminación, y los elementos en el subrango [ ret , last ) están todos en un estado válido pero no especificado, es decir, [ ret , last ) es el subrango que debe ser borrado.

Complejidad

Exactamente N aplicaciones del predicado correspondiente y cualquier proyección, donde N = ranges:: distance ( first, last ) , y N - 1 operaciones de movimiento en el peor caso.

Notas

Una llamada a ranges::remove normalmente va seguida de una llamada a la función miembro erase del contenedor, que borra los valores no especificados y reduce el tamaño físico del contenedor para que coincida con su nuevo tamaño lógico . Estas dos invocaciones juntas constituyen el llamado erase-remove idiom , que puede lograrse mediante la función libre std::erase que tiene sobrecargas para todos los contenedores estándar de secuencia , o std::erase_if que tiene sobrecargas para todos los contenedores estándar.

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 generalmente no pueden utilizarse con contenedores asociativos como std::set y std::map porque sus tipos de iterador no desreferencian a tipos MoveAssignable (las claves en estos contenedores no son modificables).

Debido a que ranges::remove toma el value por referencia, puede tener un comportamiento inesperado si es una referencia a un elemento del rango [ first , last ) .

Implementación posible

remove (1,2)
struct remove_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             class T = std::projected_value_t<I, Proj>>
    requires std::indirect_binary_predicate
                 <ranges::equal_to, std::projected<I, Proj>, const T*>
    constexpr ranges::subrange<I>
        operator()(I first, S last, const T& value, Proj proj = {}) const
    {
        first = ranges::find(std::move(first), last, value, proj);
        if (first != last)
        {
            for (I i{std::next(first)}; i != last; ++i)
                if (value != std::invoke(proj, *i))
                {
                    *first = ranges::iter_move(i);
                    ++first;
                }
        }
        return {first, last};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             class T = std::projected_value_t<ranges::iterator_t<R>, Proj>>
    requires std::permutable<ranges::iterator_t<R>> &&
             std::indirect_binary_predicate
                 <ranges::equal_to,
                  std::projected<ranges::iterator_t<R>, Proj>, const T*>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, const T& value, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value, std::move(proj));
    }
};
inline constexpr remove_fn remove {};
remove_if (3,4)
struct remove_if_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr ranges::subrange<I>
        operador()(I primero, S último, Pred pred, Proj proj = {}) const
    {
        primero = ranges::find_if(std::move(primero), último, pred, proj);
        if (primero != último)
        {
            for (I i{std::next(primero)}; i != último; ++i)
                if (!std::invoke(pred, std::invoke(proj, *i)))
                {
                    *primero = ranges::iter_move(i);
                    ++primero;
                }
        }
        return {primero, último};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_unary_predicate
                 <std::projected<ranges::iterator_t<R>, Proj>> Pred>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operador()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), pred, std::move(proj));
    }
};
inline constexpr remove_if_fn remove_if {};

Notas

Macro de prueba de características Valor Estándar Característica
__cpp_lib_algorithm_default_value_type 202403 (C++26) Inicialización por lista para algoritmos ( 1,2 )

Ejemplo

#include <algorithm>
#include <cassert>
#include <complex>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
int main()
{
    std::string v1{"No se requiere diagnóstico"};
    std::cout << std::quoted(v1) << " (v1, tamaño: " << v1.size() << ")\n";
    const auto ret = std::ranges::remove(v1, ' ');
    std::cout << std::quoted(v1) << " (v1 después de `remove`, tamaño: " << v1.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v1.begin(), ret.begin()), '^') << '\n';
    v1.erase(ret.begin(), ret.end());
    std::cout << std::quoted(v1) << " (v1 después de `erase`, tamaño: " << v1.size() << ")\n\n";
    // remove_if con predicado unario personalizado:
    auto rm = [](char c) { return !std::isupper(c); };
    std::string v2{"Substitution Failure Is Not An Error"};
    std::cout << std::quoted(v2) << " (v2, tamaño: " << v2.size() << ")\n";
    const auto [first, last] = std::ranges::remove_if(v2, rm);
    std::cout << std::quoted(v2) << " (v2 después de `remove_if`, tamaño: " << v2.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v2.begin(), first), '^') << '\n';
    v2.erase(first, last);
    std::cout << std::quoted(v2) << " (v2 después de `erase`, tamaño: " << v2.size() << ")\n\n";
    // creando una vista en un contenedor que es modificado por `remove_if`:
    for (std::string s : {"Optimización de Objetos Pequeños", "Parámetro de Plantilla No Tipo"})
        std::cout << std::quoted(s) << " => "
            << std::string_view{begin(s), std::ranges::remove_if(s, rm).begin()} << '\n';
    std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}};
    #ifdef __cpp_lib_algorithm_default_value_type
        auto e = std::ranges::remove(nums, {1, 3}); // T se deduce
    #else
        auto e = std::ranges::remove(nums, std::complex<double>{1, 3});
    #endif
    nums.erase(e.begin(), e.end());
    assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}}));
}

Salida posible:

"No _ Diagnostic _ Required" (v1, tamaño: 26)
"No_Diagnostic_Requiredired" (v1 después de `remove`, tamaño: 26)
 ^^^^^^^^^^^^^^^^^^^^^^
"No_Diagnostic_Required" (v1 después de `erase`, tamaño: 22)
"Substitution Failure Is Not An Error" (v2, tamaño: 36)
"SFINAEtution Failure Is Not An Error" (v2 después de `remove_if`, tamaño: 36)
 ^^^^^^
"SFINAE" (v2 después de `erase`, tamaño: 6)
"Small Object Optimization" => SOO
"Non-Type Template Parameter" => NTTP

Véase también

copia un rango de elementos omitiendo aquellos que cumplen criterios específicos
(objeto función de algoritmo)
elimina elementos duplicados consecutivos en un rango
(objeto función de algoritmo)
elimina elementos que cumplen criterios específicos
(plantilla de función)