それらは完全に異なるアルゴリズムです。述語が真である最初の項目を直線的find_if
に探し、範囲がソートされていることを利用して、指定された値がその中にあるかどうかを対数時間でテストします。binary_search
述語 forbinary_search
は、範囲が順序付けられる関数を指定します (おそらく、ソートに使用したのと同じ述語を使用する必要があります)。
ソートを利用して、まったく関係のない述語を満たす値を検索することはできません (find_if
とにかく使用する必要があります)。ただし、ソートされた範囲を使用するとlower_bound
、 、upper_bound
およびで存在をテストするだけでなく、それ以上のことができることに注意してくださいequal_range
。
何が目的なのかという質問はstd::binary_function
興味深いものです。
result_type
、first_argument_type
およびの typedef を提供するだけsecond_argument_type
です。これらは、テンプレート引数としてファンクターを与えられたユーザーが、これらの型を見つけて使用できるようにします。
template <class T, class BinaryFunction>
void foo(const T& a, const T& b, BinaryFunction f)
{
//declare a variable to store the result of the function call
typename BinaryFunction::result_type result = f(a, b);
//...
}
ただし、標準ライブラリで使用される唯一の場所はbind1st
、bind2nd
、not1
、などの他のファンクタ ラッパーを作成することだと思いますnot2
。(それらが他の目的に使用された場合、関数をファンクターとして使用すると、移植性がなくなるため、人々はいつでもあなたに怒鳴るでしょう。)
たとえば、次のbinary_negate
ように実装できます (GCC):
template<typename _Predicate>
class binary_negate
: public binary_function<typename _Predicate::first_argument_type,
typename _Predicate::second_argument_type, bool>
{
protected:
_Predicate _M_pred;
public:
explicit
binary_negate(const _Predicate& __x) : _M_pred(__x) { }
bool
operator()(const typename _Predicate::first_argument_type& __x,
const typename _Predicate::second_argument_type& __y) const
{ return !_M_pred(__x, __y); }
};
もちろん、operator()
単にテンプレートである可能性もあります。その場合、これらの typedef は不要になります (欠点はありますか?)。ユーザーが明示的に型定義する必要なしに、引数の型が何であるかを見つけるためのメタプログラミング手法もおそらくあります。私は、C++0x が与える力で多少邪魔になると思います-たとえば、可変引数テンプレートを使用して任意のアリティの関数の否定子を実装したい場合...
std::tr1::bind
(IMO では、C++98 のファンクターは、やなどに比べて柔軟性に欠け、原始的すぎますstd::tr1::mem_fn
が、おそらく当時、それらを機能させるために必要なメタプログラミング手法に対するコンパイラーのサポートはそれほど良くなく、おそらくその手法はまだ発見されていました。 )