cppreference.com -> C++ 関数オブジェクト

C++ 関数オブジェクト

この項目はStandard Template Library プログラミング on the Webより引用しています。引用を快く許可してくれたεπιστημηさんに感謝します。

関数オブジェクトとはoperator()を持つオブジェクトです。 関数オブジェクトはアルゴリズムのカスタマイザとして機能します。 関数オブジェクトの交換によってアルゴリズムに様々な処理を行なわせることができます。 STLの関数オブジェクトはoperator()の引数が1つのものと2つのものがあり、それぞれunary_function,binary_functionのサブクラスとなっています。 operator()の値がboolとコンパチブルである、すなわち"××である"かどうかを判定するために用いられる関数オブジェクトを"述語オブジェクト"(Predicate)といいます。

関数オブジェクトの分類

関数オブジェクトはおおまかに以下のカテゴリに分類されます。

関数オブジェクトの使い方

関数オブジェクトは多くの場合アルゴリズムの引数として用いられます。

 // 例: アルゴリズムfind_if
 template
 InputIterator
 find_if(InputIterator first, InputIterator last, Predicate pred) {
    while ( first != last && !pred(*first) )
      ++first;
    return first;
 }

find_ifはfirstから始まりlastに達しない範囲にあるイテレータiに対し、pred(*i) != false となるiを返します。int配列の中から0より大きい要素を探すには、operator()に引数として渡された値が0より大きければtrueを返す関数オブジェクトをfind_ifの第3引数に与えます:

 bool positive(int x) { return x > 0; }

 int array[] = { 0, 0, -1, 3, 0 };
 int* it = find_if(array, array+5, &positive);
 if ( it != array+5 ) {
   // 見つかった!
 }

この例では関数のポインタを関数オブジェクトとして与えています。関数のポインタfに対してf()するとその関数が呼び出されて結果を返すのでoperator()が定義されているとみなせるからです。

関数アダプタ

"0より大きい"という関数オブジェクトを利用したい場合に、比較演算を行なう関数オブジェクトgreaterを使うことはできないのでしょうか。find_ifの引数に与える関数オブジェクトpredはoperator()の引数が1つでなくてはなりません。ところがgreaterは引数を2つ要求します。positive(x)がその内部でgreater::operator()(x,0)を呼んでくれるような関数オブジェクトpositiveがあるなら、greaterからpositiveを作り出すことができます。binder1st,binder2ndはまさしくそのために用意された関数オブジェクトです。このように、既存の関数オブジェクトを修飾したり、ラッピングしたりするものを関数アダプタと呼びます。

  binder2nd< greater<int> > positive(greater<int>(),0);
  int array[] = { 0, 0, -1, 3, 0 };
  int* it = find_if(array, array+5, positive);
  if ( it != array+5 ) {
    // 見つかった!
  }