引数を2つ取る関数の第一引数に実引数をbindして,引数を一つ取る関数に変換するためのクラス.ちなみに,第二引数にbindするのはbinder2nd.もひとつちなみに、binder1stがやってることをカリー化(curring)という.
binder1stはoperator()を提供するクラスであり,それをお手軽に作るためのヘルパー関数がbind1st().ここまではsgiのサイトを見ながらの復習.
さて,本当にやりたいのは3引数を取る関数に1つの値をbindして2引数の関数を作ること.具体的には,長い文字列docと,docの中の位置を指す2つのインデックスを取り,その位置からのsuffixを辞書順に比較したい.
bool suffix_lower(const string &str, size_t lh, size_t rh) { for (;lh < str.size() && rh < str.size(); ++lh, ++rh) { if (str[lh] < str[rh]) return true; if (str[lh] > str[rh]) return false; } if (lh > rh) return true; // 最後まで一致した場合は,短い方(=インデックスが終端に到達した方)が辞書順で先になる. return false; // lh == rh の時もfalse. }
という関数を用意して,
std::vector<size_t> sa; sa.reserve(doc.size()); // docは検索対象となるドキュメント. for (size_t i = 0; i < doc.size(); ++i) sa.push_back(i); std::sort(sa.begin(), sa.end(), std::bind1st(suffix_lower, doc));
とやりたかったのだが,残念ながらコレはエラーになる.std::bind1st()は3引数を取る関数には対応していないからだ.
・・・そういえば,std::binder1st()が中途半端すぎたから,boostがちゃんと汎用的なヤツを作ってたよな・・・と思い出して、boostのドキュメントを調べてみる.あった.(http://www.boost.org/libs/bind/bind.html)
ただ,プログラムを書いているPCにboostを入れて無くて,Windowsだからapt-getだけじゃ入らないので,あとでLinux上で書くときにboost使うことにして,とりあえずでっち上げのクラスでbindしておく.
struct suffix_lower_bind : public binary_function<size_t, size_t, bool> { suffix_lower_bind(const string &doc) : doc_(doc) {} bool operator()(size_t lh, size_t rh) const { return suffix_lower(doc_, lh, rh); } private: const string &doc_; };
C++0xでは,functional系の標準ライブラリはboostが要らないくらいマシになってたら良いな。