Boost.Bindは、元々 std :: bind1st()およびstd :: bind2nd()を必要としていた機能を単純化および一般化するライブラリです。
例1.1:互換性のある関数を使用したstd :: for_each()
#include <vector>
#include <algorithm>
#include <iostream>
void print(int i)
{
std::cout << i << '\n';
}
int main()
{
std::vector<int> v{1, 3, 2};
std::for_each(v.begin(), v.end(), print);
}
std :: for_each()の3番目のパラメーターは、唯一のパラメーターを期待する関数または関数オブジェクトです。例1.1では、std :: for_each()は、コンテナーv内の数値を唯一のパラメーターとしてprint()に次々に渡します。
シグニチャがアルゴリズムの要件を満たさない関数を渡す必要がある場合、それはより困難になります。たとえば、print()で出力ストリームを追加のパラメーターとして受け入れる場合、 std :: for_each()でそのまま使用することはできなくなります。
例1.2。std :: for_each()とstd :: bind1st()
#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
class print : public std::binary_function<std::ostream*, int, void>
{
public:
void operator()(std::ostream *os, int i) const
{
*os << i << '\n';
}
};
int main()
{
std::vector<int> v{1, 3, 2};
std::for_each(v.begin(), v.end(), std::bind1st(print{}, &std::cout));
}
例1.1と同様に、例1.2はvのすべての数値を標準出力に書き込みます。ただし、今回は、出力ストリームがパラメーターとしてprint()に渡されます。これを行うために、関数print()は、 std::binary_functionから派生した関数オブジェクトとして定義されます。
Boost.Bindを使用すると、 print()を関数から関数オブジェクトに変換する必要はありません。代わりに、 boost/bind.hppで定義されている関数テンプレートboost::bind()を使用します。
例1.3:std :: for_each()とboost :: bind()
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
void print(std::ostream *os, int i)
{
*os << i << '\n';
}
int main()
{
std::vector<int> v{1, 3, 2};
std::for_each(v.begin(), v.end(), boost::bind(print, &std::cout, _1));
}
例1.3では、print()を関数オブジェクトとしてではなく、関数として使用しています。print()は2つのパラメーターを想定しているため、関数をstd :: for_each()に直接渡すことはできません。代わりに、boost :: bind()がstd :: for_each()に渡され、print()がboost :: bind()の最初のパラメーターとして渡されます。
print()は2つのパラメーターを想定しているため、 boost :: bind()にもこれらの2つのパラメーターを渡す必要があります。これらは、std::coutおよび_1へのポインタです。
_1はプレースホルダーです。Boost.Bin dは、_1から_9までのプレースホルダーを定義します。これらのプレースホルダーは、boost :: bind()に、最大数のプレースホルダーと同じ数のパラメーターを期待する関数オブジェクトを返すように指示します。例1.3のように、プレースホルダー_1のみが使用されている場合、boost :: bind()は単項関数オブジェクト(唯一のパラメーターを期待する関数オブジェクト)を返します。std :: for_each()は1つのパラメーターのみを渡すため、この場合はこれが必要です。
std :: for_each()は単項関数オブジェクトを呼び出します。関数オブジェクトに渡される値(コンテナーvからの数値)は、プレースホルダー_1の位置を取ります。boost :: bind()は、数値とstd :: coutへのポインターを受け取り、それらをprint()に転送します。
std :: bind1st()やstd :: bind2nd()のように、boost :: bind()はパラメータを値で受け取ることに注意してください。呼び出し側プログラムがstd::coutをコピーしようとするのを防ぐために、print()はストリームへのポインターを期待します。Boost.Refは、参照によってパラメーターを渡すことができる関数を提供します。
例1.4は、 boost :: bind()を使用してバイナリ関数オブジェクトを定義する方法を示しています。アルゴリズムstd::sort()を使用します。これは、3番目のパラメーターとして2進関数を期待します。
例1.4。std :: sort()とboost :: bind()
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v{1, 3, 2};
std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2));
for (int i : v)
std::cout << i << '\n';
}
例1.4では、プレースホルダー_2が使用されているため、バイナリ関数オブジェクトが作成されます。アルゴリズムstd::sort()は、コンテナーvからの2つの値を使用してこのバイナリ関数オブジェクトを呼び出し、戻り値を評価してコンテナーをソートします。関数compare()は、vを降順でソートするように定義されています。
compare()はバイナリ関数であるため、std :: sort()に直接渡すことができます。ただし、 boost :: bind()を使用すると、パラメーターの順序を変更できるため、それでも意味があります。たとえば、コンテナを昇順で並べ替えたいが、compare()を変更したくない場合は、 boost :: bind()を使用できます。
例1.5。std :: sort()とboost :: bind()およびプレースホルダーの順序の変更
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
bool compare(int i, int j)
{
return i > j;
}
int main()
{
std::vector<int> v{1, 3, 2};
std::sort(v.begin(), v.end(), boost::bind(compare, _2, _1));
for (int i : v)
std::cout << i << '\n';
}