std::ranges::equal_range
| Défini dans l'en-tête <algorithm>
|
||
| Signature d'appel |
||
template< std::forward_iterator I, std::sentinel_for<I> S,
class T, class Proj = std::identity,
std::indirect_strict_weak_order
<const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr ranges::subrange<I> equal_range( I first, S last, const T& value,
Comp comp = {}, Proj proj = {} );
|
(1) | (depuis C++20) (jusqu'à C++26) |
template< std::forward_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
class T = std::projected_value_t<I, Proj>,
std::indirect_strict_weak_order
<const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr ranges::subrange<I> equal_range( I first, S last, const T& value,
Comp comp = {}, Proj proj = {} );
|
(depuis C++26) | |
template< ranges::forward_range R,
class T, class Proj = std::identity,
std::indirect_strict_weak_order
<const T*, std::projected<ranges::iterator_t<R>,
Proj>> Comp = ranges::less >
constexpr ranges::borrowed_subrange_t<R>
equal_range( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
|
(2) | (depuis C++20) (jusqu'à C++26) |
template< ranges::forward_range R,
class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
std::indirect_strict_weak_order
<const T*, std::projected<ranges::iterator_t<R>,
Proj>> Comp = ranges::less >
constexpr ranges::borrowed_subrange_t<R>
equal_range( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
|
(depuis C++26) | |
value dans la plage [first, last).La plage [first, last) doit être au moins partiellement ordonnée par rapport à value, c'est-à-dire qu'elle doit satisfaire à toutes les exigences suivantes :
- partitionnée par rapport à
element < valueoucomp(element, value)(c'est-à-dire que tous les éléments pour lesquels l'expression esttrueprécèdent tous les éléments pour lesquels l'expression estfalse). - partitionnée par rapport à
!(value < element)ou!comp(value, element). - pour tous les éléments, si
element < valueoucomp(element, value)esttruealors!(value < element)ou!comp(value, element)est égalementtrue.
Une plage complètement triée répond à ces critères.
La vue renvoyée est construite à partir de deux itérateurs, l'un pointant vers le premier élément qui est pas inférieur à value et un autre pointant vers le premier élément plus grand que value. Le premier itérateur peut également être obtenu avec std::ranges::lower_bound(), le second avec std::ranges::upper_bound().
r comme plage source, comme si la plage ranges::begin(r) était utilisée comme first et ranges::end(r) comme last.Les entités de type fonction décrites sur cette page sont des objets fonctions d'algorithme (informellement appelés niebloids), c'est-à-dire :
- Les listes d'arguments template explicites ne peuvent pas être spécifiées lors de l'appel à l'un d'eux.
- Aucun d'eux n'est visible par la recherche dépendante des arguments.
- Lorsque l'un d'eux est trouvé 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.
Paramètres
| first, last | - | la paire itérateur-sentinelle définissant la plage d'éléments à examiner |
| r | - | la plage d'éléments à examiner |
| value | - | valeur à comparer aux éléments |
| comp | - | si le premier argument est inférieur au second (c'est-à-dire s'il est ordonné avant) |
| proj | - | projection à appliquer aux éléments |
Valeur de retour
std::ranges::subrange contenant une paire d'itérateurs définissant la plage souhaitée, le premier pointant vers le premier élément qui est pas inférieur à value et le second pointant vers le premier élément plus grand que value.
S'il n'y a aucun élément pas inférieur à value, le dernier itérateur (itérateur égal à last ou ranges::end(r)) est renvoyé comme premier élément. De même, s'il n'y a aucun élément plus grand que value, le dernier itérateur est renvoyé comme deuxième élément.
Complexité
Le nombre de comparaisons effectuées est logarithmique par rapport à la distance entre first et last (au plus 2 * log2(last - first) + O(1) comparaisons). Cependant, pour un itérateur qui ne modélise pas random_access_iterator, le nombre d'incréments d'itérateur est linéaire.
Implémentation possible
struct equal_range_fn
{
template<std::forward_iterator I, std::sentinel_for<I> S,
class Proj = std::identity, class T = std::projected_value_t<I, Proj>,
std::indirect_strict_weak_order
<const T*, std::projected<I, Proj>> Comp = ranges::less>
constexpr ranges::subrange<I>
operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const
{
return ranges::subrange
(
ranges::lower_bound(first, last, value, std::ref(comp), std::ref(proj)),
ranges::upper_bound(first, last, value, std::ref(comp), std::ref(proj))
);
}
template<ranges::forward_range R, class Proj = std::identity,
class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
std::indirect_strict_weak_order
<const T*, std::projected<ranges::iterator_t<R>,
Proj>> Comp = ranges::less>
constexpr ranges::borrowed_subrange_t<R>
operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), value,
std::ref(comp), std::ref(proj));
}
};
inline constexpr equal_range_fn equal_range;
|
Notes
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type |
202403 |
(C++26) | Initialisation de liste pour les algorithmes (1,2) |
Exemple
#include <algorithm>
#include <compare>
#include <complex>
#include <iostream>
#include <vector>
struct S
{
int number {};
char name {};
// note: name is ignored by these comparison operators
friend bool operator== (const S s1, const S s2) { return s1.number == s2.number; }
friend auto operator<=>(const S s1, const S s2) { return s1.number <=> s2.number; }
friend std::ostream& operator<<(std::ostream& os, S o)
{
return os << '{' << o.number << ", '" << o.name << "'}";
}
};
void println(auto rem, const auto& v)
{
for (std::cout << rem; const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
// note: not ordered, only partitioned w.r.t. S defined below
std::vector<S> vec
{
{1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {4, 'D'}, {4,'G'}, {3,'F'}
};
const S value{2, '?'};
namespace ranges = std::ranges;
auto a = ranges::equal_range(vec, value);
println("1. ", a);
auto b = ranges::equal_range(vec.begin(), vec.end(), value);
println("2. ", b);
auto c = ranges::equal_range(vec, 'D', ranges::less {}, &S::name);
println("3. ", c);
auto d = ranges::equal_range(vec.begin(), vec.end(), 'D', ranges::less {}, &S::name);
println("4. ", d);
using CD = std::complex<double>;
std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};
auto cmpz = [](CD x, CD y) { return x.real() < y.real(); };
#ifdef __cpp_lib_algorithm_default_value_type
auto p3 = ranges::equal_range(nums, {2, 0}, cmpz);
#else
auto p3 = ranges::equal_range(nums, CD{2, 0}, cmpz);
#endif
println("5. ", p3);
}
Sortie :
1. {2, 'B'} {2, 'C'} {2, 'D'}
2. {2, 'B'} {2, 'C'} {2, 'D'}
3. {2, 'D'} {4, 'D'}
4. {2, 'D'} {4, 'D'}
5. (2,2) (2,1)
Voir aussi
(C++20) |
trouve le premier élément non inférieur à la valeur donnée en utilisant la recherche binaire (objet fonction d'algorithme) |
(C++20) |
trouve le premier élément supérieur à la valeur donnée en utilisant la recherche binaire (objet fonction d'algorithme) |
(C++20) |
détermine si un élément existe dans une plage en utilisant la recherche binaire (objet fonction d'algorithme) |
(C++20) |
divise une plage d'éléments en deux groupes (objet fonction d'algorithme) |
(C++20) |
détermine si deux ensembles d'éléments sont identiques (objet fonction d'algorithme) |
| trouve la plage d'éléments correspondant à la valeur donnée en utilisant la recherche binaire (fonction template) |