Movatterモバイル変換


[0]ホーム

URL:


野良C++erの雑記帳

ある区間の上限/下限を求める

STL の upper_bound / lower_bound を使ってみたらハマったので、日記のネタに。


結論を書くと、
std::upper_bound( first, last, x ) は、区間 [iter, last ) がstd::equal_range( first, last, x ) の上界となるようなiter を、
std::lower_bound( first, last, x ) は、区間 [ first,iter ) がstd::equal_range( first, last, x ) の下界となるようなiter を、
それぞれ求める関数です。


つまり、得られたiter は、
upper_bound の場合は上界の最初の要素を指すイテレータで、これは分かりやすいですが、
lower_bound の場合は、下界の最後の要素の「次を」指すイテレータになります。
下界の最後の要素、つまり下限を求めたい場合は、イテレータを一つ前に戻す必要がある、ということです。
まぁ考えてみれば当たり前なのですが、うっかりハマってしまったので、日記に書き残しておく次第。


というか、最初から、ある区間に対して上限と下限を求める関数があればいいんですよね。
こんな感じで:

http://ideone.com/oARV9

#include<algorithm>#include<iterator>#include<boost/optional.hpp>template<class FwdIter,class T>inline boost::optional<typename std::iterator_traits<FwdIter>::reference>  sup( FwdIter first, FwdIter last, Tconst& x ){  first = std::upper_bound( first, last, x );if( first != last ) {return *first;  }else {return boost::none;  }}template<class BidirIter,class T>inline boost::optional<typename std::iterator_traits<BidirIter>::reference>  inf( BidirIter first, BidirIter last, Tconst& x ){  last = std::lower_bound( first, last, x );if( first != last ) {return *--last;  }else {return boost::none;  }}#include<iostream>int main(){int a[] = {1,2,3,3,4,6 };  std::size_tconst n =sizeof(a) /sizeof(a[0]);  std::cout << *sup( a, a+n,3 ) << std::endl;  std::cout << *inf( a, a+n,3 ) << std::endl;}

結果がイテレータではなく optional な参照なのは、 inf において「見つからなかった」ことを示す適切なイテレータがない為。
last を返す、でもいいのですが、意味論的におかしいので*1、ならば optional の方がいいかな、という判断です。
range-base なら、こういう場合に悩まなくて済む気もしますね。

*1:意味論的には first の前の要素を指すイテレータを返したい

検索

引用をストックしました

引用するにはまずログインしてください

引用をストックできませんでした。再度お試しください

限定公開記事のため引用できません。

読者です読者をやめる読者になる読者になる

[8]ページ先頭

©2009-2025 Movatter.jp