std::ranges::upper_bound
| 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 I upper_bound( 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 I upper_bound( 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_iterator_t<R>
upper_bound( 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_iterator_t<R>
upper_bound( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
|
(depuis C++26) | |
[first, last) qui est plus grand que value, ou last si aucun élément de ce type n'est trouvé.
La plage [first, last) doit être partitionnée par rapport à l'expression ou !comp(value, element), c'est-à-dire que tous les éléments pour lesquels l'expression est true doivent précéder tous les éléments pour lesquels l'expression est false. Une plage entièrement triée satisfait ce critère.r comme plage source, comme si on utilisait ranges::begin(r) 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 explicites de paramètres de template ne peuvent pas être spécifiées lors de l'appel de l'un d'entre eux.
- Aucun d'entre eux n'est visible par la recherche dépendante des arguments.
- Lorsque l'un d'entre 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 partiellement ordonnée des éléments à examiner |
| r | - | la plage partiellement ordonnée à examiner |
| value | - | valeur à comparer aux éléments |
| pred | - | prédicat à appliquer aux éléments projetés |
| proj | - | projection à appliquer aux éléments |
Valeur de retour
Itérateur pointant vers le premier élément qui est supérieur à value , ou last si aucun élément de ce type n'est trouvé.
Complexité
Le nombre de comparaisons et d'applications de la projection effectuées est logarithmique par rapport à la distance entre
first
et
last
(au plus
log
2
(last - first) + O(1)
comparaisons et applications de la projection). Cependant, pour un itérateur qui ne modélise pas
random_access_iterator
, le nombre d'incrémentations d'itérateur est linéaire.
Implémentation possible
struct upper_bound_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 I operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const { I it; std::iter_difference_t<I> count, step; count = ranges::distance(first, last); while (count > 0) { it = first; step = count / 2; ranges::advance(it, step, last); if (!comp(value, std::invoke(proj, *it))) { first = ++it; count -= step + 1; } else count = step; } return first; } 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_iterator_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 upper_bound_fn upper_bound; |
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 <iostream> #include <iterator> #include <vector> int main() { namespace ranges = std::ranges; std::vector<int> data{1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6}; { auto lower = ranges::lower_bound(data.begin(), data.end(), 4); auto upper = ranges::upper_bound(data.begin(), data.end(), 4); ranges::copy(lower, upper, std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n'; } { auto lower = ranges::lower_bound(data, 3); auto upper = ranges::upper_bound(data, 3); ranges::copy(lower, upper, std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n'; } 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 it = ranges::upper_bound(nums, {2, 0}, cmpz); #else auto it = ranges::upper_bound(nums, CD{2, 0}, cmpz); #endif assert((*it == CD{3, 0})); }
Sortie :
4 4 4 3 3 3 3
Voir aussi
(C++20) |
trouve la plage d'éléments correspondant à la valeur donnée en utilisant la recherche binaire (objet fonction d'algorithme) |
(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) |
divise une plage d'éléments en deux groupes (objet fonction d'algorithme) |
| trouve le premier élément supérieur à la valeur donnée en utilisant la recherche binaire (modèle de fonction) |