std::ranges::upper_bound
| Definiert in Header <algorithm>
|
||
| Aufrufsignatur |
||
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) | (seit C++20) (bis 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 = {} );
|
(seit 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) | (seit C++20) (bis 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 = {} );
|
(seit C++26) | |
[first, last) zeigt, das größer als value ist, oder last, wenn kein solches Element gefunden wird.
Der Bereich [first, last) muss in Bezug auf den Ausdruck oder !comp(value, element) partitioniert sein, d. h., alle Elemente, für die der Ausdruck true ist, müssen allen Elementen vorausgehen, für die der Ausdruck false ist. Ein vollständig sortierter Bereich erfüllt dieses Kriterium.r als Quellbereich, als ob ranges::begin(r) als first und ranges::end(r) als last verwendet würde.Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als Niebloids bekannt), das heißt:
- Beim Aufruf einer von ihnen können keine expliziten Vorlagenargumentlisten angegeben werden.
- Keine von ihnen ist für argumentabhängige Suche sichtbar.
- Wenn eine von ihnen durch normale unqualifizierte Suche als Name links vom Funktionsaufrufoperator gefunden wird, wird argumentabhängige Suche unterdrückt.
Parameter
| first, last | - | das Iterator-Sentinel-Paar, das den teilweise geordneten Bereich der zu untersuchenden Elemente definiert |
| r | - | der teilweise geordnete Bereich, der untersucht werden soll |
| value | - | Wert, mit dem die Elemente verglichen werden |
| pred | - | Prädikat, das auf die projizierten Elemente angewendet wird |
| proj | - | Projektion, die auf die Elemente angewendet wird |
Rückgabewert
Iterator, der auf das erste Element zeigt, das größer als value ist, oder last , falls kein solches Element gefunden wird.
Komplexität
Die Anzahl der Vergleiche und Anwendungen der Projektion ist logarithmisch im Abstand zwischen
first
und
last
(höchstens
log
2
(last - first) + O(1)
Vergleiche und Anwendungen der Projektion). Für einen Iterator, der nicht
random_access_iterator
modelliert, ist die Anzahl der Iterator-Inkremente jedoch linear.
Mögliche Implementierung
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; |
Hinweise
| Feature-Test Makro | Wert | Std | Funktion |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | Listeninitialisierung für Algorithmen ( 1,2 ) |
Beispiel
#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})); }
Ausgabe:
4 4 4 3 3 3 3
Siehe auch
(C++20) |
ermittelt den Bereich der Elemente, die dem gegebenen Wert entsprechen, mithilfe einer binären Suche (algorithm function object) |
(C++20) |
ermittelt das erste Element, das nicht kleiner als der gegebene Wert ist, mithilfe einer binären Suche (algorithm function object) |
(C++20) |
teilt einen Bereich von Elementen in zwei Gruppen auf (algorithm function object) |
| ermittelt das erste Element, das größer als der gegebene Wert ist, mithilfe einer binären Suche (function template) |