std::unique
| Défini dans l'en-tête <algorithm>
|
||
template< class ForwardIt >
ForwardIt unique( ForwardIt first, ForwardIt last );
|
(1) | (constexpr depuis C++20) |
template< class ExecutionPolicy, class ForwardIt >
ForwardIt unique( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last );
|
(2) | (depuis C++17) |
template< class ForwardIt, class BinaryPred >
ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPred p );
|
(3) | (constexpr depuis C++20) |
template< class ExecutionPolicy,
class ForwardIt, class BinaryPred >
ForwardIt unique( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, BinaryPred p );
|
(4) | (depuis C++17) |
Supprime tous les éléments sauf le premier de chaque groupe consécutif d'éléments équivalents de la plage [first, last) et renvoie un itérateur pointant après la nouvelle fin de la plage.
operator==.operator== n'établit pas une relation d'équivalence, le comportement est indéfini.p.p n'établit pas une relation d'équivalence, le comportement est indéfini.policy.true:
|
|
(jusqu'à C++20) |
|
|
(depuis C++20) |
Explication
La suppression s'effectue en décalant les éléments de la plage de telle manière que les éléments à ne pas supprimer apparaissent au début de la plage.
- Le décalage est effectué par copy assignment (until C++11) move assignment (since C++11) .
- L'opération de suppression est stable : l'ordre relatif des éléments non supprimés reste inchangé.
-
La séquence sous-jacente de
[first,last)n'est pas raccourcie par l'opération de suppression. En considérant result comme l'itérateur retourné :
-
-
Tous les itérateurs dans
[result,last)restent déréférençables .
-
Tous les itérateurs dans
|
(depuis C++11) |
Paramètres
| first, last | - | la paire d'itérateurs définissant la plage d'éléments à traiter |
| policy | - | la politique d'exécution à utiliser |
| p | - |
prédicat binaire qui retourne
true
si les éléments doivent être traités comme égaux.
La signature de la fonction de prédicat doit être équivalente à ce qui suit : bool pred ( const Type1 & a, const Type2 & b ) ;
Bien que la signature n'ait pas besoin d'avoir
const
&
, la fonction ne doit pas modifier les objets qui lui sont passés et doit pouvoir accepter toutes les valeurs de type (éventuellement const)
|
| Exigences de type | ||
-
ForwardIt
doit satisfaire aux exigences de
LegacyForwardIterator
.
|
||
-
ForwardIt
doit satisfaire aux exigences de
MoveAssignable
.
|
||
Valeur de retour
Un
ForwardIt
vers la nouvelle fin de la plage.
Complexité
Étant donné N comme std:: distance ( first, last ) :
Exceptions
Les surcharges avec un paramètre de modèle nommé
ExecutionPolicy
signalent les erreurs comme suit :
-
Si l'exécution d'une fonction invoquée dans le cadre de l'algorithme lève une exception et que
ExecutionPolicyfait partie des politiques standard , std::terminate est appelée. Pour tout autreExecutionPolicy, le comportement est défini par l'implémentation. - Si l'algorithme ne parvient pas à allouer de la mémoire, std::bad_alloc est levée.
Implémentation possible
Voir également les implémentations dans libstdc++ , libc++ , et 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; } |
Notes
Un appel à
unique
est généralement suivi d'un appel à la fonction membre
erase
du conteneur pour supprimer effectivement les éléments du conteneur.
Exemple
#include <algorithm> #include <iostream> #include <vector> int main() { // un vecteur contenant plusieurs éléments dupliqués 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); // supprimer les doublons consécutifs (adjacents) auto last = std::unique(v.begin(), v.end()); // v contient maintenant {1 2 1 3 4 5 4 x x x}, où 'x' est indéterminé v.erase(last, v.end()); print(2); // tri suivi de unique, pour supprimer tous les doublons std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5} print(3); last = std::unique(v.begin(), v.end()); // v contient maintenant {1 2 3 4 5 x x}, où 'x' est indéterminé v.erase(last, v.end()); print(4); }
Sortie :
@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
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Applicable à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| LWG 202 | C++98 |
le comportement était incertain si les éléments sont
comparés en utilisant une relation de non-équivalence |
le comportement est
indéfini dans ce cas |
Voir aussi
| trouve les deux premiers éléments adjacents qui sont égaux (ou satisfont un prédicat donné) (modèle de fonction & objet fonction d'algorithme) | |
(C++20) |
|
| crée une copie d'une certaine plage d'éléments qui ne contient pas de doublons consécutifs (modèle de fonction & objet fonction d'algorithme) | |
(C++20) |
|
| supprime les éléments satisfaisant des critères spécifiques (modèle de fonction & objet fonction d'algorithme) | |
(C++20)(C++20) |
|
| supprime les éléments en double consécutifs (fonction membre publique de std::list<T,Allocator>)
| |
| supprime les éléments en double consécutifs (fonction membre publique de std::forward_list<T,Allocator>)
| |
(C++20) |
supprime les éléments en double consécutifs dans une plage (objet fonction d'algorithme) |