std::ranges:: remove, std::ranges:: remove_if
|
Défini dans l'en-tête
<algorithm>
|
||
|
Signature d'appel
|
||
| (1) | ||
|
template
<
std::
permutable
I,
std::
sentinel_for
<
I
>
S,
class
T,
class
Proj
=
std::
identity
>
|
(depuis C++20)
(jusqu'à C++26) |
|
|
template
<
std::
permutable
I,
std::
sentinel_for
<
I
>
S,
class
Proj
=
std::
identity
,
|
(depuis C++26) | |
| (2) | ||
|
template
<
ranges::
forward_range
R,
class
T,
class
Proj
=
std::
identity
>
|
(depuis C++20)
(jusqu'à C++26) |
|
|
template
<
ranges::
forward_range
R,
class
Proj
=
std::
identity
,
|
(depuis C++26) | |
|
template
<
std::
permutable
I,
std::
sentinel_for
<
I
>
S,
class
Proj
=
std::
identity
,
|
(3) | (depuis C++20) |
|
template
<
ranges::
forward_range
R,
class
Proj
=
std::
identity
,
|
(4) | (depuis C++20) |
Supprime tous les éléments satisfaisant des critères spécifiques de la plage
[
first
,
last
)
et retourne une sous-plage
[
ret
,
last
)
, où
ret
est un itérateur pointant après la nouvelle fin de la plage.
La suppression s'effectue en décalant (par assignation de déplacement) les éléments de la plage de telle manière que les éléments à ne pas supprimer apparaissent au début de la plage. L'ordre relatif des éléments restants est préservé et la taille physique du conteneur reste inchangée. Les itérateurs pointant vers un élément entre la nouvelle fin logique et la fin physique de la plage restent déréférençables, mais les éléments eux-mêmes ont des valeurs non spécifiées (conformément à la MoveAssignable post-condition).
Les entités de type fonction décrites sur cette page sont des algorithm function objects (informellement appelées niebloids ), c'est-à-dire :
- Les listes d'arguments de modèle explicites ne peuvent pas être spécifiées lors de l'appel de l'une d'entre elles.
- Aucune d'entre elles n'est visible pour la recherche dépendante des arguments .
- Lorsque l'une d'entre elles est trouvée par la recherche non qualifiée normale comme nom à gauche de l'opérateur d'appel de fonction, la recherche dépendante des arguments est inhibée.
Table des matières |
Paramètres
| first, last | - | la paire itérateur-sentinelle définissant la plage des éléments à traiter |
| r | - | la plage d'éléments à traiter |
| value | - | la valeur des éléments à supprimer |
| pred | - | prédicat à appliquer aux éléments projetés |
| proj | - | projection à appliquer aux éléments |
Valeur de retour
{
ret, last
}
, où
[
first
,
ret
)
est le sous-intervalle résultant après suppression, et les éléments dans le sous-intervalle
[
ret
,
last
)
sont tous dans un état valide mais non spécifié, c'est-à-dire que
[
ret
,
last
)
est le sous-intervalle à effacer.
Complexité
Exactement N applications du prédicat correspondant et de toute projection, où N = ranges:: distance ( first, last ) , et N - 1 opérations de déplacement au pire.
Notes
Un appel à
ranges::remove
est généralement suivi d'un appel à la fonction membre
erase
du conteneur, qui efface les valeurs non spécifiées et réduit la taille
physique
du conteneur pour correspondre à sa nouvelle taille
logique
. Ces deux invocations constituent ensemble ce qu'on appelle l'
idiome erase-remove
, qui peut être réalisé par la fonction libre
std::erase
qui possède des
surcharges
pour tous les conteneurs
séquentiels
standards, ou
std::erase_if
qui possède des
surcharges
pour
tous
les conteneurs standards.
Les fonctions membres de conteneur de nom similaire member functions list::remove , list::remove_if , forward_list::remove , et forward_list::remove_if suppriment les éléments retirés.
Ces algorithmes ne peuvent généralement pas être utilisés avec des conteneurs associatifs tels que std::set et std::map car leurs types d'itérateurs ne se déréférencent pas vers des types MoveAssignable (les clés dans ces conteneurs ne sont pas modifiables).
Parce que
ranges::remove
prend la
value
par référence, il peut avoir un comportement inattendu s'il s'agit d'une référence à un élément de la plage
[
first
,
last
)
.
Implémentation possible
| supprimer (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 {}; |
Notes
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | Initialisation par liste pour les algorithmes ( 1,2 ) |
Exemple
#include <algorithm> #include <cassert> #include <complex> #include <cctype> #include <iomanip> #include <iostream> #include <string> #include <string_view> #include <vector> int main() { std::string v1{"Aucun - Diagnostic - Requis"}; std::cout << std::quoted(v1) << " (v1, taille : " << v1.size() << ")\n"; const auto ret = std::ranges::supprimer(v1, ' '); std::cout << std::quoted(v1) << " (v1 après `remove`, taille : " << 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 après `erase`, taille : " << v1.size() << ")\n\n"; // remove_if avec prédicat unaire personnalisé : auto rm = [](char c) { return !std::isupper(c); }; std::string v2{"Substitution Failure Is Not An Error"}; std::cout << std::quoted(v2) << " (v2, taille : " << v2.size() << ")\n"; const auto [first, last] = std::ranges::remove_if(v2, rm); std::cout << std::quoted(v2) << " (v2 après `remove_if`, taille : " << v2.size() << ")\n"; std::cout << ' ' << std::string(std::distance(v2.begin(), first), '^') << '\n'; v2.erase(first, last); std::cout << std::quoted(v2) << " (v2 après `erase`, taille : " << v2.size() << ")\n\n"; // création d'une vue dans un conteneur qui est modifié par `remove_if` : for (std::string s : {"Optimisation des Petits Objets", "Paramètre de Modèle Non-Type"}) 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::supprimer(nums, {1, 3}); // T est déduit #else auto e = std::ranges::supprimer(nums, std::complex<double>{1, 3}); #endif nums.erase(e.begin(), e.end()); assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}})); }
Sortie possible :
"No _ Diagnostic _ Required" (v1, taille : 26) "No_Diagnostic_Requiredired" (v1 après `remove`, taille : 26) ^^^^^^^^^^^^^^^^^^^^^^ "No_Diagnostic_Required" (v1 après `erase`, taille : 22) "Substitution Failure Is Not An Error" (v2, taille : 36) "SFINAEtution Failure Is Not An Error" (v2 après `remove_if`, taille : 36) ^^^^^^ "SFINAE" (v2 après `erase`, taille : 6) "Small Object Optimization" => SOO "Non-Type Template Parameter" => NTTP
Voir aussi
|
(C++20)
(C++20)
|
copie une plage d'éléments en omettant ceux qui satisfont des critères spécifiques
(objet fonction algorithme) |
|
(C++20)
|
supprime les éléments en double consécutifs dans une plage
(objet fonction algorithme) |
|
supprime les éléments satisfaisant des critères spécifiques
(modèle de fonction) |