関数アダプタは、関数を関数オブジェクトとして使用できるようにするために、大域関数やメンバー関数を適合させるクラスのインスタンスです。また、関数アダプタは 3.5 節で説明するように、関数または関数オブジェクトの動作の変更に使用することもできます。各関数アダプタは、大域関数やメンバー関数を使用するコンストラクタを提供します。また、アダプタは、関連付けられた大域関数やメンバー関数へ呼び出しを転送する括弧演算子も提供します。
pointer_to_unary_function と pointer_to_binary_function のテンプレートは、引数が 1 つか 2 つの大域関数を適合させます。このようなアダプタは、直接適用することができます。また、ptr_fun 関数テンプレートを使用して、適切なアダプタが自動的に作成されるようにすることも可能です。たとえば、次のように単純な times3 関数を適合させ、整数のベクトルに適用することができます。
int times3(int x) { return 3*x; } int a{} {1,2,3,4,5}; vector<int> v(a,a+5), v2; transform(v.begin(),v.end(),v2.end(),ptr_fun(times3));
また、アダプタを適用できた場合は、新しく適合された関数オブジェクトがベクトルへ渡されます。
pointer_to_unary_function<int,int> pf(times3); transform(v.begin(),v.end(),v2.end(),pf);
この例では、ptr_fun を使用することによって pointer_to_unary_function で必要とされる型をコンパイラで推測できるようになるという利点を示します。
テンプレートの mem_fun ファミリは、大域関数ではなく、メンバー関数を適合させます。たとえば、既定のリストセットの各リストをソートする場合、mem_fun_t または単純な mem_fun を使用して、セットの各要素にリストソートのメンバー関数を適合させることができます。
set<list<int>* > s; // リストとともにセットを初期化する // セット内の各リストをソートする for_each(s.begin(),s.end(),mem_fun(&list<int>::sort)); // セット内の各リストがソートされた
リストでは汎用ソートアルゴリズムを使用できないため、mem_fun を使用する必要があります。また、これは標準コンテナで保持される多相特性を持つオブジェクトにアクセスするための最も簡単な方法でもあります。たとえば、仮想引き出し関数は、次のような標準的な 形状の階層 のあらゆる部分のオブジェクトのコレクションで呼び出すことができます。
// 形状の階層 class shape { virtual void draw(); }; class circle : public shape { void draw(); }; class square : public shape { void draw(); }; // 形状のベクトルをアセンブルする circle c; square s; vector<shape*> v; v.push_back(&s); v.push_back(&c); // 1 つずつ draw を呼び出す for_each(v.begin(),v.end(), mem_fun(&shape::draw));
大域関数アダプタと同様に、各メンバー関数アダプタはクラスのテンプレートと、関連付けられた関数のテンプレートで構成されます。クラスは実際のアダプタであり、使用中のクラスのインスタンスを作成することによって、関数がクラスの使用を簡単にします。たとえば上記の例では、ユーザーが mem_fun_t を作成し、for_each アルゴリズムに渡されるようにすることができます。
mem_fun_t<shape> mf(&shape::draw); for_each(v.begin(),v.end(),mf);
また、mem_fun 関数のテンプレートは、mem_fun_t で必要とされる型をコンパイラで推測できるようにすることによって、mem_fun_t アダプタの使用を容易にします。
標準 C++ ライブラリは、引数がない関数や引数が 1 つの関数のためのメンバー関数アダプタを提供します。このような関数は、引数が 2 つ以上ある関数に簡単に拡張することができます。