DESC
function(関数) object といわれるもので
Cでいうコールバック関数ポインタの働きをする
関数のように動作する Object のこと
演算子 overload のうち、() をoverload したもの
POINT
使いどころ
より優れたコールバックを記述すること.
C などの手続き型プログラミング言語にコールバックは関数へのポインタによって実現することができる
コールバックの内外に状態変数を渡すことが難しい
strategy デザインパターンの完全な具現化であり、抜き差し可能な振る舞いを促進するもの。
STL では Template による. Functor を多用している
operator=()
operator()()
// 関数 object
class Cout()
{
public:
void operator()( int num ){
cout < < num < < endl;
}
};
// Client
int main(){
Cout func;
func( 5 ); // call back を呼ぶ
}
// template 化する
template < class T >
class Cout()
{
public:
void operator()( T num ){ cout < < num < < endl; }
};
std::for_each( c.begin(), c.end(), Cout< float>() );
->
どんな std:cout() に対応できるものならば、すべて可能 ( Template の原則 . )
STL と組み合わせることで、より強力な tool になる
// cpp の callback との比較
int comp_func( int a, int b )
{
return a > b;
}
// functor
class compCls
{
public:
operator()( int a, int b ){
return a > b;
}
};
// 宣言
template < class compFunctor>
void sort( int *p, int nr, compFunctor c );
// usr
int main()
{
int data[] = {0, 1, 2};
compCls func; // 上記 cls を使用
sort( data, 3, func );
// 使用する際は
func(); とする ?
}
// 二つの要素の順序関係を定義するコールバック関数を用いて並べ替えを行うルーチンの例
/* Callback function */
int compare_function(int A, int B) {
return (A < B);
}
// C の並べ替え関数の定義
void sort_ints(int* begin_items, int num_items, int (*cmpfunc)(int, int) );
int main() {
int items[] = {4, 3, 1, 2};
sort_ints(items, sizeof(items)/sizeof(int), compare_function);
}
// C++ では通常の関数の代わりに、operator() メンバー関数を定義して 関数呼び出し演算子をオーバーロードすることで、
// 関数オブジェクトを利用できる
class compare_class {
public:
bool operator()(int A, int B) {
return (A < B);
}
};
// C++ の並べ替え関数の定義 -> template になっている.
template < class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
int main() {
int items[] = {4, 3, 1, 2};
compare_class functor;
// PtrFunc ではなく, Object をわたす.
// Object なので, VarMem, FuncMem にアクセス可能.
sort_ints(items, sizeof(items)/sizeof(int), functor);
}
// Functor を別の用途で使ってみる.
functor_class Y;
int result = Y( a, b );
// Inline 化できるため, C の PtrFunc よりも性能がよい.
struct IncrementFunctor {
void operator()(int&i) { ++i; }
};
// 通常の関数による Increment
void increment_function(int&i) { ++i; }
template< typename InputIterator, typename Function >
Function for_each(InputIterator first, InputIterator last, Function f) {
for ( ; first != last; ++first) {
f(*first);
}
return f;
}
int A[] = {1, 4, 2, 8, 5, 7};
const int N = sizeof(A) / sizeof(a[0]);
for_each(A, A + N, IncrementFunctor());
for_each(A, A + N, increment_function);
// 状態も保持できる.
#include < iostream>
#include < iterator>
#include < algorithm>
// 要はクラス名が関数名になる.
class countfrom
{
private:
// 状態.
int count;
public:
countfrom(int n) : count(n) {}
int operator()() { return count++; }
};
int main() {
std::generate_n(std::ostream_iterator< int>(std::cout, "\n"), 11, countfrom(10));
return 0;
}