std:: upper_bound
|
ヘッダーで定義
<algorithm>
|
||
| (1) | ||
|
template
<
class
ForwardIt,
class
T
>
ForwardIt upper_bound
(
ForwardIt first, ForwardIt last,
|
(C++20以降 constexpr)
(C++26まで) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
>
|
(C++26以降) | |
| (2) | ||
|
template
<
class
ForwardIt,
class
T,
class
Compare
>
ForwardIt upper_bound
(
ForwardIt first, ForwardIt last,
|
(C++20以降 constexpr)
(C++26まで) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
,
|
(C++26以降) | |
区分化された範囲
[
first
,
last
)
内で、
value
よりも後に順序付けられる最初の要素を検索します。
|
|
(C++20以前) |
|
std :: upper_bound ( first, last, value, std:: less { } ) と等価です。 |
(C++20以降) |
[
first
,
last
)
内において、
bool
(
comp
(
value,
*
iter
)
)
が
true
となる最初のイテレータです。そのような
iter
が存在しない場合は
last
を返します。
目次 |
パラメータ
| first, last | - | パーティション分割された要素の範囲を定義するイテレータのペア range |
| value | - | 要素と比較する値 |
| comp | - |
第1引数が第2引数の前に順序付けられる場合に
true
を返す二項述語
述語関数のシグネチャは以下と同等であるべきです: bool pred ( const Type1 & a, const Type2 & b ) ;
シグネチャが
const
&
を持つ必要はないが、関数は渡されたオブジェクトを変更してはならず、
value category
に関係なく型(おそらくconstの)
|
| 型要件 | ||
-
ForwardIt
は
LegacyForwardIterator
の要件を満たさなければならない。
|
||
-
Compare
は
BinaryPredicate
の要件を満たさなければならない。
Compare
を満たす必要はない。
|
||
戻り値
範囲の最初の要素を指すイテレータ
[
first
,
last
)
において
value
より大きい最初の要素、またはそのような要素が見つからない場合は
last
を返します。
計算量
与えられた N を std:: distance ( first, last ) として:
しかし、
ForwardIt
が
LegacyRandomAccessIterator
でない場合、イテレータのインクリメント回数は
N
に対して線形となる。特に、
std::map
、
std::multimap
、
std::set
、および
std::multiset
のイテレータはランダムアクセスではないため、それらのメンバ関数
upper_bound
を使用することが推奨される。
実装例
以下の実装も参照してください: libstdc++ および libc++ 。
| upper_bound (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value) { return std::upper_bound(first, last, value, std::less{}); } |
| upper_bound (2) |
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type, class Compare> ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp) { ForwardIt it; typename std::iterator_traits<ForwardIt>::difference_type count, step; count = std::distance(first, last); while (count > 0) { it = first; step = count / 2; std::advance(it, step); if (!comp(value, *it)) { first = ++it; count -= step + 1; } else count = step; } return first; } |
注記
std::upper_bound
は
[
first
,
last
)
が分割されていることのみを要求しますが、このアルゴリズムは通常、
[
first
,
last
)
がソートされている場合に使用されるため、任意の
value
に対して二分探索が有効となります。
[
first
,
last
)
内の任意のイテレータ
iter
に対して、
std::upper_bound
は
value
<
*
iter
および
comp
(
value,
*
iter
)
が適切に形成されることを要求します。一方、
std::lower_bound
は代わりに
*
iter
<
value
および
comp
(
*
iter, value
)
が適切に形成されることを要求します。
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | リスト初期化 アルゴリズム用 ( 1,2 ) |
例
#include <algorithm> #include <cassert> #include <complex> #include <iostream> #include <vector> struct PriceInfo { double price; }; int main() { const std::vector<int> data{1, 2, 4, 5, 5, 6}; for (int i = 0; i < 7; ++i) { // iより大きい最初の要素を検索 auto upper = std::upper_bound(data.begin(), data.end(), i); std::cout << i << " < "; upper != data.end() ? std::cout << *upper << " at index " << std::distance(data.begin(), upper) : std::cout << "not found"; std::cout << '\n'; } std::vector<PriceInfo> prices{{100.0}, {101.5}, {102.5}, {102.5}, {107.3}}; for (double to_find : {102.5, 110.2}) { auto prc_info = std::upper_bound(prices.begin(), prices.end(), to_find, [](double value, const PriceInfo& info) { return value < info.price; }); prc_info != prices.end() ? std::cout << prc_info->price << " at index " << prc_info - prices.begin() : std::cout << to_find << " not found"; 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 = std::upper_bound(nums.cbegin(), nums.cend(), {2, 0}, cmpz); #else auto it = std::upper_bound(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz); #endif assert((*it == CD{3, 0})); }
出力:
0 < 1 at index 0 1 < 2 at index 1 2 < 4 at index 2 3 < 4 at index 2 4 < 5 at index 3 5 < 6 at index 5 6 < not found 107.3 at index 4 110.2 not found
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| LWG 270 | C++98 |
Compare
は
Compare
要件を満たすことが要求され、
T
は
LessThanComparable であることが要求された(厳密弱順序が必要) |
分割のみが要求される;
異種比較が許可される |
| LWG 384 | C++98 | 最大 log 2 (N)+1 回の比較が許可されていた | log 2 (N)+O(1) に修正 |
| LWG 577 | C++98 | last を返すことができなかった | 許可される |
| LWG 2150 | C++98 |
[
first
,
last
)
内に
iter
が存在し、
bool ( comp ( value, * iter ) ) が true である場合、
std::upper_bound
は
[
iter
,
last
)
内の任意のイテレータを返すことができた
|
iter 以降のイテレータは返せない |
関連項目
|
特定のキーに一致する要素の範囲を返す
(関数テンプレート) |
|
|
指定された値
以上
の最初の要素を指すイテレータを返す
(関数テンプレート) |
|
|
要素の範囲を2つのグループに分割する
(関数テンプレート) |
|
|
(C++11)
|
分割された範囲の分割点を特定する
(関数テンプレート) |
|
(C++20)
|
特定の値
より大きい
最初の要素を指すイテレータを返す
(アルゴリズム関数オブジェクト) |
|
指定されたキー
より大きい
最初の要素を指すイテレータを返す
(
std::set<Key,Compare,Allocator>
の公開メンバ関数)
|
|
|
指定されたキー
より大きい
最初の要素を指すイテレータを返す
(
std::multiset<Key,Compare,Allocator>
の公開メンバ関数)
|