Namespaces
Variants

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

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namensraum std::ranges
Nicht modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
       
       
Permutationsoperationen
Faltungsoperationen
Numerische Operationen
(C++23)            
Operationen auf nicht initialisiertem Speicher
Rückgabetypen
 
Definiert in Header <algorithm>
Aufrufsignatur
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) (seit C++20)
(bis 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 = {} );
(seit 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) (seit C++20)
(bis 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 = {} );
(seit 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) (seit 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) (seit C++20)

Entfernt alle Elemente, die bestimmte Kriterien erfüllen, aus dem Bereich [first, last) und gibt einen Teilbereich [ret, last) zurück, wobei ret ein End-Iterator für das neue Ende des Bereichs ist.

1) Entfernt alle Elemente, die gleich value sind, unter Verwendung von std::invoke(proj, *i) == value zum Vergleich.
3) Entfernt alle Elemente, für die std::invoke(pred, std::invoke(proj, *i)) true zurückgibt.
2,4) Wie (1,3), verwendet jedoch r als Bereich, als ob ranges::begin(r) als first und ranges::end(r) als last verwendet würden.

Das Entfernen erfolgt durch Verschieben (mittels Zuweisungsverschiebung) der Elemente im Bereich, sodass die nicht zu entfernenden Elemente am Anfang des Bereichs erscheinen. Die relative Reihenfolge der verbleibenden Elemente bleibt erhalten, und die physische Größe des Containers ändert sich nicht. Iteratoren, die auf ein Element zwischen dem neuen logischen Ende und dem physischen Ende des Bereichs zeigen, sind weiterhin dereferenzierbar, aber die Elemente selbst haben nicht spezifizierte Werte (gemäß der MoveAssignable-Nachbedingung).

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als niebloids bekannt), das heißt:

Parameter

first, last - das Iterator-Sentinel-Paar, das den Bereich der zu verarbeitenden Elemente definiert
r - der Bereich der zu verarbeitenden Elemente
value - der Wert der zu entfernenden Elemente
pred - Prädikat, das auf die projizierten Elemente angewendet wird
proj - Projektion, die auf die Elemente angewendet wird

Rückgabewert

{ ret, last } , wobei [ first , ret ) der resultierende Teilbereich nach der Entfernung ist, und die Elemente im Teilbereich [ ret , last ) sich alle in einem gültigen aber unspezifizierten Zustand befinden, d.h. [ ret , last ) ist der zu löschende Teilbereich.

Komplexität

Genau N Anwendungen des entsprechenden Prädikats und jeglicher Projektion, wobei N = ranges:: distance ( first, last ) , und N - 1 Move-Operationen im schlimmsten Fall.

Hinweise

Ein Aufruf von ranges::remove wird typischerweise gefolgt von einem Aufruf der erase -Memberfunktion eines Containers, welche die unspezifizierten Werte löscht und die physische Größe des Containers an die neue logische Größe anpasst. Diese beiden Aufrufe bilden zusammen das sogenannte Erase-Remove-Idiom , das durch die freie Funktion std::erase erreicht werden kann, die Überladungen für alle standardmäßigen Sequenz -Container besitzt, oder durch std::erase_if , das Überladungen für alle standardmäßigen Container bereitstellt.

Die ähnlich benannten Container- Memberfunktionen list::remove , list::remove_if , forward_list::remove und forward_list::remove_if löschen die entfernten Elemente.

Diese Algorithmen können in der Regel nicht mit assoziativen Containern wie std::set und std::map verwendet werden, da ihre Iteratortypen nicht auf MoveAssignable -Typen dereferenzieren (die Schlüssel in diesen Containern sind nicht veränderbar).

Da ranges::remove den value als Referenz übernimmt, kann es unerwartetes Verhalten verursachen, falls es sich um eine Referenz auf ein Element des Bereichs [ first , last ) handelt.

Mögliche Implementierung

entfernen (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>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        first = ranges::find_if(std::move(first), last, pred, proj);
        if (first != last)
        {
            for (I i{std::next(first)}; i != last; ++i)
                if (!std::invoke(pred, std::invoke(proj, *i)))
                {
                    *first = ranges::iter_move(i);
                    ++first;
                }
        }
        return {first, last};
    }
    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>
        operator()(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 {};

Hinweise

Feature-Test Makro Wert Std Feature
__cpp_lib_algorithm_default_value_type 202403 (C++26) Listeninitialisierung für Algorithmen ( 1,2 )

Beispiel

#include <algorithm>
#include <cassert>
#include <complex>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
int main()
{
    std::string v1{"Keine - Diagnose - Erforderlich"};
    std::cout << std::quoted(v1) << " (v1, Größe: " << v1.size() << ")\n";
    const auto ret = std::ranges::remove(v1, ' ');
    std::cout << std::quoted(v1) << " (v1 nach `remove`, Größe: " << 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 nach `erase`, Größe: " << v1.size() << ")\n\n";
    // remove_if mit benutzerdefiniertem unären Prädikat:
    auto rm = [](char c) { return !std::isupper(c); };
    std::string v2{"Substitution Failure Is Not An Error"};
    std::cout << std::quoted(v2) << " (v2, Größe: " << v2.size() << ")\n";
    const auto [first, last] = std::ranges::remove_if(v2, rm);
    std::cout << std::quoted(v2) << " (v2 nach `remove_if`, Größe: " << v2.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v2.begin(), first), '^') << '\n';
    v2.erase(first, last);
    std::cout << std::quoted(v2) << " (v2 nach `erase`, Größe: " << v2.size() << ")\n\n";
    // Erstellen einer Ansicht in einen Container, der durch `remove_if` modifiziert wird:
    for (std::string s : {"Small Object Optimization", "Non-Type Template Parameter"})
        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 wird abgeleitet
    #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}}));
}

Mögliche Ausgabe:

"No _ Diagnostic _ Required" (v1, Größe: 26)
"No_Diagnostic_Requiredired" (v1 nach `remove`, Größe: 26)
 ^^^^^^^^^^^^^^^^^^^^^^
"No_Diagnostic_Required" (v1 nach `erase`, Größe: 22)
"Substitution Failure Is Not An Error" (v2, Größe: 36)
"SFINAEtution Failure Is Not An Error" (v2 nach `remove_if`, Größe: 36)
 ^^^^^^
"SFINAE" (v2 nach `erase`, Größe: 6)
"Small Object Optimization" => SOO
"Non-Type Template Parameter" => NTTP

Siehe auch

kopiert einen Bereich von Elementen unter Auslassung derjenigen, die bestimmte Kriterien erfüllen
(Algorithmus-Funktionsobjekt)
entfernt aufeinanderfolgende doppelte Elemente in einem Bereich
(Algorithmus-Funktionsobjekt)
entfernt Elemente, die bestimmte Kriterien erfüllen
(Funktions-Template)