Namespaces
Variants

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

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Permutation operations
Fold operations
Operations on uninitialized storage
Return types
Definiert im Header <algorithm>
Aufrufsignatur
(1)
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 = { } ) ;
(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)
(2)
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 = { } ) ;
(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 Past-the-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 für den Vergleich.
3) Entfernt alle Elemente, für die std:: invoke ( pred, std:: invoke ( proj, * i ) ) den Wert true zurückgibt.
2,4) Gleich wie (1,3) , verwendet jedoch r als Bereich, als ob ranges:: begin ( r ) als first und ranges:: end ( r ) als last verwendet würde.

Das Entfernen erfolgt durch Verschieben (mittels Move-Zuweisung) der Elemente im Bereich in einer Weise, dass 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 unspezifizierte Werte (gemäß der MoveAssignable Nachbedingung).

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithm Function Objects (informell bekannt als Niebloids ), das heißt:

Inhaltsverzeichnis

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)