在std :: vector <std :: string>上使用find_if和bind2nd以及string :: compare </std :: string>

时间:2009-09-04 12:13:49

标签: c++ stl

这似乎是一个学术问题,但我仍然对答案非常感兴趣:

我有一个字符串s的向量,我希望在其中找到给定的字符串findme。这可以使用像

这样的东西来完成
find(s.begin(), s.end(), findme);

我的问题是:必须有一种方法可以使用find_if和STL字符串的compare方法作为谓词,但是如何做?像

这样的东西
find_if(s.begin(), s.end(), bind2nd(mem_fun_ref(&string::compare), string("findme")) );

不起作用,因为compare方法有几个重载,编译器不知道选择哪一个。

作为第二步:我使用find_if而不是find的动机是我有一个从具有字符串属性name的类派生的对象向量,我想找到一个具有给定名称的对象。这是否可行(没有编写额外的函数用作谓词)?


编辑:正如使用Boost提到的一些(大多数:)答案 - 我宁愿不必为此包含Boost。 (据我所知,大多数Boost库都是“唯一”模板,因此应该有一种不使用Boost的方法。)

4 个答案:

答案 0 :(得分:5)

一个选项是将成员函数指针强制转换为合适的类型。你要忘记的另一件事是std :: string :: compare对于相等的字符串返回0,所以你还需要否定functor。总而言之:

std::find_if(
    vec.begin(), vec.end(),
    std::not1(
        std::bind2nd(
            std::mem_fun_ref(static_cast<int (std::string::*)(const char*)const>(&std::string::compare)),
            "findme"
        )
    )
);

关于反对提升的理由:它的模板比STL功能头中的模板更灵活。它要么是提升,要么等待C ++ 0x lambdas(我相信在这种情况下会是更好的方式)或者你自己写一些助手。目前它不能简单:

std::find_if(vec.begin(), vec.end(), boost::bind(&X::name, _1) == "findme");

仅供参考,C ++ 0x将添加std :: bind,类似于boost :: bind,但似乎重载operator ==的便利性不会出现。

答案 1 :(得分:3)

自己选择正确的过载。

int (string::*compare)(const string&) const;
compare = &string::compare;
find_if(s.begin(), s.end(), bind2nd( mem_fun_ref(compare), string("findme")));

但是你会对引用问题“有效STL的第50项”的引用感到困惑。 而boost.Bind lib或boost.Lambda就是解决方案。

int (string::*compare)(const string&) const;
compare = &string::compare;
find_if(s.begin(), s.end(), bind(compare, _1, "findme")==0);

find_if(s.begin(), s.end(), bind2nd(std::equal_to<string>(), string("findme")));

答案 2 :(得分:1)

如果某个函数有重载函数,您可以将该函数转换为正确的签名 (void (*)(int,int))(&f)

对于你的第二个问题,如果你使用boost,你可以做这样的事情,

find_if(s.begin(), s.end(), boost::bind(std::equal_to<string>(), boost::bind(&SomeClass::name, _1), name);

答案 3 :(得分:0)

我想你会发现,如果你试图将几个函数放在一起,语法会很快变得不合适。你尝试过这样的事吗?

find_if(s.begin(), s.end(), bind2nd(mem_fun_ref(&string::compare), "findme"));

这是否与char *重载不匹配?

相关问题