C++
某所でデリゲートと関数ポインタが話題になっているで、ここでは boost.function を。
boost.function はありとあらゆる関数表現を統一して扱えるというもの。boost.function がなければ、かなり厄介な作業を強いられるだろう(特に boost.bind と boost.lambda の返値は凶悪なので)。
function<bool (int, int)>
と書けば、int の引数を 2 つ持ち、bool を返す関数「のようなもの」は何でも受け入れる事ができる。古いコンパイラでは「bool (int, int)」と書けないので、他の手段を用いなければならないが、古いコンパイラなんて誰も使わないよね。
以下は、引数が偶数かどうかを返す関数(のようなもの)を扱った例。
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/function.hpp>
using namespace std;
using namespace boost;
template <typename T>
bool is_even(const T& x){
return (x % 2 == 0);
}
template <typename T>
struct even{
bool operator()(const T& x) const{
return (x % 2 == 0);
}
bool is_even(const T& x) const{
return (x % 2 == 0);
}
};
int main(){
// 普通の関数ポインタ
function<bool (int)> f1 = is_even<int>;
// 関数オブジェクト
function<bool (int)> f2 = even<int>();
// メンバ関数(のインスタンスを束縛した関数)
even<int> e;
function<bool (int)> f3 = bind(&even<int>::is_even, &e, ::_1);
// メンバ関数
function<bool (even<int>*, int)> fe = &even<int>::is_even;
// メンバ関数(のインスタンスを束縛した関数その 2)
function<bool (int)> f4 = bind(fe, &e, ::_1);
// ラムダ
function<bool (int)> f5 = lambda::_1 % 2 == 0;
// わざわざ function を使う必要はないけど、使用例
int a[] = {1, 2, 3, 4, 7};
// f1 の部分は f2~f5 に置き換え可能
int count = count_if(a, sizeof(a) / sizeof(a[0]), f1);
cout << count << endl;
return 0;
}