4

最近、boost::lambda または boost::phoenix で解決できると思われる問題に遭遇しましたが、正しい構文を取得できなかったため、別の方法で解決しました。私がやりたかったのは、特定の長さよりも短く、別のコンテナーにない「文字列」内のすべての要素を削除することでした。

これは私の最初の試みです:

std::vector<std::string> strings = getstrings();
std::set<std::string> others = getothers();
strings.erase(std::remove_if(strings.begin(), strings.end(), (_1.length() < 24 &&  others.find(_1) == others.end())), strings.end());

私がそれをやった方法はこれでした:

struct Discard
{
    bool operator()(std::set<std::string> &cont, const std::string &s)
    {
        return cont.find(s) == cont.end() && s.length() < 24;
    }
};

lines.erase(std::remove_if( lines.begin(), lines.end(), boost::bind<bool>(Discard(), old_samples, _1)), lines.end());
4

2 に答える 2

3

ラムダ化関数呼び出しには boost::labmda::bind が必要です。たとえば、長さ < 24 の部分は次のようになります。

bind(&string::length, _1) < 24

編集

set::find が難しい理由については、"Head Geek" の投稿を参照してください。彼は正しい set::find オーバーロードを解決するためにそれを手に入れました (その部分をコピーしました)、しかし彼は重要な boost::ref() を見逃していました -- これが end() との比較が常に失敗した理由です (コンテナがコピーされました) .

int main()
{
  vector<string> strings = getstrings();
  set<string> others = getothers();
  set<string>::const_iterator (set<string>::*findFn)(const std::string&) const = &set<string>::find;
  strings.erase(
    remove_if(strings.begin(), strings.end(),
        bind(&string::length, _1) < 24 &&
        bind(findFn, boost::ref(others), _1) == others.end()
      ), strings.end());
  copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, ", "));
  return 0;
}
于 2008-10-17T23:57:49.280 に答える
2

呼び出し以外の主な問題bind(Adam Mitz はその部分で正しかった)は、オーバーロードされた関数であるため、呼び出しstd::set<std::string>::findで直接指定できないことです。次のように、どちらを使用するかをbindコンパイラに伝える必要があります。 find

using namespace boost::lambda;
typedef std::vector<std::string> T1;
typedef std::set<std::string> T2;

T1 strings = getstrings();
T2 others = getothers();

T2::const_iterator (T2::*findFn)(const std::string&) const=&T2::find;
T2::const_iterator othersEnd=others.end();

strings.erase(std::remove_if(strings.begin(), strings.end(),
    (bind(&std::string::length, _1) < 24
        && bind(findFn, boost::ref(others), _1) == othersEnd)),
    strings.end());

これはコンパイルされますが、理由はまだわかりません...find関数は を返さないothers.end()ため、何も削除されません。まだその部分に取り組んでいます。

編集: 訂正、find関数は を返しますothers.end()が、比較はそれを認識していません。どうしてか分かりません。

LATER EDIT: Adam のコメントのおかげで、何がうまくいかなかったのかがわかり、問題を修正しました。意図したとおりに動作するようになりました。

(私の完全なテスト プログラムを見たい場合は、編集履歴を見てください。)

于 2008-10-18T00:37:14.737 に答える