2012-11-23 9 views
12

私は特定の値だけを含むようにベクトルをフィルタリングしようとしています。追加パラメータを述語に渡すことはできますか?

ベクトルには値 "abc"の要素のみが含まれていることを確認してください。

今、私はremove_copy_ifでこれを達成しようとしています。

stdのアルゴリズムのいずれかを使用するときに、追加のパラメータを述語に渡す方法はありますか?

std::vector<std::string> first, second; 
first.push_back("abc"); 
first.push_back("abc"); 
first.push_back("def"); 
first.push_back("abd"); 
first.push_back("cde"); 
first.push_back("def"); 

std::remove_copy_if(first.begin(), first.end(), second.begin(), is_invalid); 

私は、述語として、以下の関数を渡すことを望んだが、それは、これは単なるremove_copy_ifと、次により検討されている現在の値を比較終わるだろうと可能性が高いようです。

私はおそらくこの間違いに近づいていると思いますので、どんな提案も感謝します!

おかげ

+0

ちょうど、同じ要素だけのベクトルを使用していますか? – Zane

+0

私はできるだけシンプルに私の例を作ろうとしたので意味がありました:)私がこれをしたのは、(正規表現を使って)特定のパターンに合ったベクトルから要素を取り除くことでした。 – noko

答えて

16

代わりファンクタを定義:

struct is_invalid 
{ 
    is_invalid(const std::string& a_wanted) : wanted(a_wanted) {} 
    std::string wanted; 
    bool operator()(const std::string& str) 
    { 
     return str.compare(wanted) != 0; 
    } 
}; 

std::remove_copy_if(first.begin(), 
        first.end(), 
        second.begin(), 
        is_invalid("abc")); 

またはC++ 11ラムダを使用する場合:

std::string wanted("abc"); 
std::remove_copy_if(first.begin(), first.end(), second.begin(), 
    [&wanted](const std::string& str) 
    { 
     return str.compare(wanted) != 0; 
    }); 

注出力をそのベクター、second,remove_copy_if()への呼び出しの前に要素を持っている必要があります。

// Create 'second' after population of 'first'. 
// 
std::vector<std::string> second(first.size()); 

std::string wanted = "abc"; 
int copied_items = 0; 
std::remove_copy_if(first.begin(), first.end(), second.begin(), 
    [&wanted, &copied_items](const std::string& str) -> bool 
    { 
     if (str.compare(wanted) != 0) return true; 
     copied_items++; 
     return false; 
    }); 
second.resize(copied_items); 

ファンクタ述語がコピーされると多くの努力がcopied_items情報を保持するために必要とされます。推奨ソリューションについては、Pass std algos predicates by reference in C++を参照してください。

+0

このソリューションを使用しようとすると「未定義の参照」に関するエラーが発生するようですが、何が起きているのかについてのアイデアはありますか? – noko

+0

@noko、ideoneなどにコードを投稿できますか?コンパイラはC++ 11ラムダをサポートする必要があります(g ++では、 '-std = C++ 0x'コンパイラスイッチを使用する必要があります)。 – hmjd

+0

心配しないで、ClassName ::を関数の前に追加するのを忘れてしまった:( – noko

8

はファンクタを作る、またはstd/boost::bindを使用しています。バインドと

struct is_invalid 
{ 
public: 
    is_invalid(const std::string& w):wanted(w) { } 
    bool operator() (const std::string& str) 
    { 
     return str.compare(wanted) != 0; 
    } 
private: 
    std::string wanted; 
}; 

std::remove_copy_if(first.begin(), first.end(), second.begin(), is_invalid("abc")); 

bool is_invalid(const std::string &str, const std::string &wanted) 
{ 
    return str.compare(wanted) != 0; 
} 

std::remove_copy_if(first.begin(), first.end(), second.begin(), 
boost::bind(is_invalid, _1, "abc")); 
関連する問題