你能将附加参数传递给谓词吗?

时间:2012-11-23 08:28:40

标签: c++ predicate

我正在尝试过滤矢量,因此它只包含特定值。

e.g。确保向量仅包含值“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和下一个bool is_invalid(const std::string &str, const std::string &wanted) { return str.compare(wanted) != 0; } 检查的当前值。

{{1}}

我有一种感觉我可能正在接近这个错误所以任何建议都会受到赞赏!

由于

2 个答案:

答案 0 :(得分:18)

改为定义仿函数:

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使用lambda:

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++

答案 1 :(得分: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"));