【原】C++11 bind
9745 ワード
bindは関数バインドのためのテンプレートのセットです.関数をバインドする場合は、パラメータの一部またはすべてを指定するか、パラメータを指定しないか、各パラメータ間の順序を調整できます.指定されていないパラメータでは、プレースホルダ_を使用できます.1、_2、_3で表します.-1バインドされた関数の1番目のパラメータを表します.2はバインドされた関数の2番目のパラメータを表し,その他は順に類推する.
bindは、通常の関数、関数オブジェクト、クラスのメンバー関数、クラスのメンバー変数にバインドできます.それぞれご紹介します.
1、普通関数
2、関数オブジェクト
3、クラスのメンバー関数
4、クラスのメンバー変数
bindはネストバインドも可能である.年齢取得インタフェースint GetAge()を持つCPersonクラスがあり、CPersonオブジェクトのvectorが現在存在し、ソートする必要がある場合はbindを以下のように使用できます.
整数のvectorがあると仮定し、20より大きいが30未満の整数の個数を取得するには、次のようにします.
bindを使用する場合、特に注意すべき点がいくつかありますが、以下、一つ一つ紹介します.
1、値を指定したパラメータに対してbindが返す関数オブジェクトはこれらの値を保存し、デフォルトは値伝達で保存します.次のコードを考慮します.
bindが返す関数オブジェクトを呼び出すと、nは0に等しくなります.これはbind時にnのコピーが伝達されるためである.nへの参照が必要な場合は、refまたはcref関数を使用します.たとえば、次のようにします.
2、bindの最初のパラメータは関数オブジェクトであり、プレースホルダで代用することはできません.次のコードを考慮します.
この場合、applyテンプレートを使用できます.applyテンプレートの最初のパラメータは、入力された関数オブジェクトであり、後にいくつかのパラメータがあり、関数オブジェクトのパラメータを表すことができます.例:
applyを使用すると、vctFuncの要素をプレースホルダとして渡すことができます.参照コードは次のとおりです.
bindは、通常の関数、関数オブジェクト、クラスのメンバー関数、クラスのメンバー変数にバインドできます.それぞれご紹介します.
1、普通関数
1 void nine_arguments(int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9);
2 int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9;
3 bind(nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7(i1,i2,i3,i4,i5,i6,i7,i8,i9);
4 bind(nine_arguments,i9,i2,i1,i6,i3,i8,_1,_2,_1)(i8,i9);
5 bind(nine_arguments, i9,i2,i1,i6,i3,i8,i4,i5,i7)();
2、関数オブジェクト
1 class CStudent
2 {
3 public:
4 void operator() (string strName, int nAge)
5 {
6 cout << strName << " : " << nAge << endl;
7 }
8 };
9 bind(CStudent(), "Mike", _1)(12);
3、クラスのメンバー関数
1 struct TAdd
2 {
3 int Add(int x,int y)
4 {
5 return x+y;
6 }
7 };
8 TAdd tAdd;
9 TAdd *p = new TAdd();
10 shared_ptr<TAdd> *q(p);
11 bind(TAdd::Add, tAdd, 2, 3)();
12 bind(TAdd::Add, p, 2, 3)();
13 bind(TAdd::Add, q, 2, 3)();
4、クラスのメンバー変数
1 void Output(const string &name)
2 {
3 cout << name << endl;
4 }
5
6 map<int, string> map1;
7 for_each(map1.begin(), map1.end(), bind(Output, bind(map<int,
8 string>::value_type::second, _1)));
bindはネストバインドも可能である.年齢取得インタフェースint GetAge()を持つCPersonクラスがあり、CPersonオブジェクトのvectorが現在存在し、ソートする必要がある場合はbindを以下のように使用できます.
1 vector<CPerson> vctPerson;
2 sort(vctPerson.begin(), vctPerson.end(), bind(less<int>(),
3 bind(CPerson::GetAge, _1), bind(CPerson::GetAge, _2)));
整数のvectorがあると仮定し、20より大きいが30未満の整数の個数を取得するには、次のようにします.
1 count_if(vctNum.begin(), vctNum.end, bind(logic_and<bool>(),
2 bind(greater<int>(), _1, 20), bind(less<int>(), _1, 30)));
bindを使用する場合、特に注意すべき点がいくつかありますが、以下、一つ一つ紹介します.
1、値を指定したパラメータに対してbindが返す関数オブジェクトはこれらの値を保存し、デフォルトは値伝達で保存します.次のコードを考慮します.
1 void inc(int &a) { a++; }
2 int n = 0;
3 bind(inc, n)();
bindが返す関数オブジェクトを呼び出すと、nは0に等しくなります.これはbind時にnのコピーが伝達されるためである.nへの参照が必要な場合は、refまたはcref関数を使用します.たとえば、次のようにします.
1 bind(inc, ref(n))(); // n 1
2、bindの最初のパラメータは関数オブジェクトであり、プレースホルダで代用することはできません.次のコードを考慮します.
1 typedef function<void (int)> Func;
2 vector<Func> vctFunc;
3 for_each(vctFunc.begin(), vctFunc.end(), bind(_1, 5)); //
この場合、applyテンプレートを使用できます.applyテンプレートの最初のパラメータは、入力された関数オブジェクトであり、後にいくつかのパラメータがあり、関数オブジェクトのパラメータを表すことができます.例:
1 apply<void> a; // void
2 a(f); // f()
3 a(f, x); // f(x)
4 a(f, x, y); // f(x, y)
applyを使用すると、vctFuncの要素をプレースホルダとして渡すことができます.参照コードは次のとおりです.
1 for_each(vctFunc.begin(), vctFunc.end(), bind(apply<void>(), _1, 5));