std::unique
| Definiert in Header <algorithm> |
||
template< class ForwardIt > ForwardIt unique( ForwardIt first, ForwardIt last ); |
(1) | (constexpr seit C++20) |
| template< class ExecutionPolicy, class ForwardIt > ForwardIt unique( ExecutionPolicy&& policy, |
(2) | (seit C++17) |
template< class ForwardIt, class BinaryPred > ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPred p ); |
(3) | (constexpr seit C++20) |
| template< class ExecutionPolicy, class ForwardIt, class BinaryPred > |
(4) | (seit C++17) |
Entfernt alle bis auf das erste Element aus jeder aufeinanderfolgenden Gruppe äquivalenter Elemente aus dem Bereich [first, last) und gibt einen Iterator nach dem Ende für das neue Ende des Bereichs zurück.
|
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> ist true. |
(bis C++20) |
|
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> ist true. |
(seit C++20) |
Inhalt |
[bearbeiten] Erklärung
Das Entfernen geschieht durch Verschieben der Elemente im Bereich so, dass die nicht zu entfernenden Elemente am Anfang des Bereichs erscheinen.
- Das Verschieben erfolgt durch Kopierzuweisung(bis C++11)Verschiebungszuweisung(seit C++11).
- Der Entfernungsvorgang ist stabil: Die relative Reihenfolge der nicht zu entfernenden Elemente bleibt erhalten.
- Die zugrunde liegende Sequenz von
[first,last)wird durch den Entfernungsvorgang nicht verkürzt. Sei result der zurückgegebene Iterator
- Alle Iteratoren in
[result,last)sind weiterhin dereferenzierbar.
- Alle Iteratoren in
|
(seit C++11) |
[bearbeiten] Parameter
| first, last | - | das Iteratorenpaar, das den Bereich der zu verarbeitenden Elemente definiert |
| policy | - | die Ausführungsrichtlinie, die verwendet werden soll |
| p | - | binäre Prädikatfunktion, die true zurückgibt, wenn die Elemente als gleich behandelt werden sollen. Die Signatur der Prädikatfunktion sollte äquivalent zur folgenden sein: bool pred(const Type1 &a, const Type2 &b); Obwohl die Signatur nicht zwingend const & haben muss, darf die Funktion die ihr übergebenen Objekte nicht modifizieren und muss alle Werte vom Typ (möglicherweise const) |
| Typanforderungen | ||
-ForwardIt muss die Anforderungen von LegacyForwardIterator erfüllen. | ||
-Der Typ von dereferenziertem ForwardIt muss die Anforderungen von MoveAssignable erfüllen. | ||
[bearbeiten] Rückgabewert
Ein ForwardIt auf das neue Ende des Bereichs.
[bearbeiten] Komplexität
Gegeben sei N als std::distance(first, last).
[bearbeiten] Ausnahmen
Die Überladungen mit einem Template-Parameter namens ExecutionPolicy berichten Fehler wie folgt
- Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst und
ExecutionPolicyeine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jede andereExecutionPolicyist das Verhalten implementierungsabhängig. - Wenn dem Algorithmus der Speicher zur Neuzuweisung fehlt, wird std::bad_alloc ausgelöst.
[bearbeiten] Mögliche Implementierung
Siehe auch die Implementierungen in libstdc++, libc++ und MSVC STL.
| unique (1) |
|---|
template<class ForwardIt> ForwardIt unique(ForwardIt first, ForwardIt last) { if (first == last) return last; ForwardIt result = first; while (++first != last) if (!(*result == *first) && ++result != first) *result = std::move(*first); return ++result; } |
| unique (3) |
template<class ForwardIt, class BinaryPredicate> ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p) { if (first == last) return last; ForwardIt result = first; while (++first != last) if (!p(*result, *first) && ++result != first) *result = std::move(*first); return ++result; } |
[bearbeiten] Hinweise
Ein Aufruf von unique wird typischerweise gefolgt von einem Aufruf einer erase-Memberfunktion eines Containers, um die Elemente tatsächlich aus dem Container zu entfernen.
[bearbeiten] Beispiel
#include <algorithm> #include <iostream> #include <vector> int main() { // a vector containing several duplicate elements std::vector<int> v{1, 2, 1, 1, 3, 3, 3, 4, 5, 4}; auto print = [&](int id) { std::cout << "@" << id << ": "; for (int i : v) std::cout << i << ' '; std::cout << '\n'; }; print(1); // remove consecutive (adjacent) duplicates auto last = std::unique(v.begin(), v.end()); // v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate v.erase(last, v.end()); print(2); // sort followed by unique, to remove all duplicates std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5} print(3); last = std::unique(v.begin(), v.end()); // v now holds {1 2 3 4 5 x x}, where 'x' is indeterminate v.erase(last, v.end()); print(4); }
Ausgabe
@1: 1 2 1 1 3 3 3 4 5 4 @2: 1 2 1 3 4 5 4 @3: 1 1 2 3 4 4 5 @4: 1 2 3 4 5
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 202 | C++98 | war das Verhalten unklar, wenn die Elemente mit einer Nicht-Äquivalenzrelation verglichen werden |
Das Verhalten ist in diesem Fall nicht definiert. |
[bearbeiten] Siehe auch
| Findet die ersten beiden benachbarten Elemente, die gleich sind (oder eine gegebene Bedingung erfüllen) (Funktionstempelat) | |
| Erstellt eine Kopie eines Bereichs von Elementen, die keine aufeinanderfolgenden Duplikate enthält (Funktionstemplate) | |
| entfernt Elemente, die bestimmte Kriterien erfüllen (Funktionstemplate) | |
| entfernt aufeinanderfolgende doppelte Elemente (öffentliche Memberfunktion von std::list<T,Allocator>) | |
| entfernt aufeinanderfolgende doppelte Elemente (öffentliche Memberfunktion von std::forward_list<T,Allocator>) | |
| (C++20) |
Entfernt aufeinanderfolgende doppelte Elemente in einem Bereich (Algorithmus-Funktionsobjekt) |