function
さて、汎用バインダbindによって生成された関数オブジェクトを変数に格納し、いくつものアルゴリズムで使いまわすことを考えてみましょう。そのためにはbindが生成した関数オブジェクトの'型'をもつ変数を宣言しなければなりません。
cout << typeid(tr1::bind(&Sandwich::make, _1, _2, _3)).name();
class boost::_bi::bind_t<class std::basic_string<char, struct std::char_traits<char>,class std::allocator<char> >, class boost::_mfi::cmf2<class std::basic_string<char, struct std::char_traits<char>,class std::allocator<char> >, class Sandwich,class std::basic_string<char, struct std::char_traits<char>,class std::allocator<char> > const &, class std::basic_string<char,struct std::char_traits<char>, class std::allocator<char> > const &>, class boost::_bi::list3<class boost::arg<1>,class boost::arg<2>,class boost::arg<3> > >
……とてつもなく複雑な型が作られています。これでは変数を宣言できません。
クラステンプレートfunctionは関数オブジェクトの汎用的な'型'として機能します。
#include <iostream> #include <algorithm> #include <functional> #include <boost/tr1/functional.hpp> using namespace std; // x < y なら true を返す bool less_int(int x, int y) { return x < y; } // 昇順/降順のどちらにも使える比較関数 template<typename T> bool compare(T x, T y, bool descend) { return descend ? (x < y) : (y < x); } int main() { const int N = 8; int data[N] = { 0, -1, 1, -2, 2, -3, 3, 4 }; // template引数がちょっと特殊。 // 戻り値 (変数,変数...) という形式。 tr1::function<bool (int,int)> comp; // 昇順にソート using namespace tr1::placeholders; comp = tr1::bind(&compare<int>, _1, _2, true); sort(data, data+N, comp); for ( int i = 0; i < N; ++i ) cout << data[i] << ' '; cout << endl; // 同じく昇順にソート comp = &less_int; sort(data, data+N, comp); for ( int i = 0; i < N; ++i ) cout << data[i] << ' '; cout << endl; // これもやっぱり降順にソート comp = less<int>(); sort(data, data+N, comp); for ( int i = 0; i < N; ++i ) cout << data[i] << ' '; cout << endl; }
