如何使用Compare对象std :: find?

时间:2010-04-16 23:35:16

标签: c++ stl vector find compare

我对std::find的界面感到困惑。为什么不用Compare对象告诉它如何比较两个对象?

如果我可以传递一个Compare对象,我可以使下面的代码工作,我希望按值进行比较,而不是直接比较指针值:

typedef std::vector<std::string*> Vec;
Vec vec;
std::string* s1 = new std::string("foo");
std::string* s2 = new std::string("foo");
vec.push_back(s1);
Vec::const_iterator found = std::find(vec.begin(), vec.end(), s2);
// not found, obviously, because I can't tell it to compare by value
delete s1;
delete s2;

以下是推荐的方法吗?

template<class T>
struct MyEqualsByVal {
  const T& x_;
  MyEqualsByVal(const T& x) : x_(x) {}
  bool operator()(const T& y) const {
    return *x_ == *y;
  }
};
// ...
vec.push_back(s1);
Vec::const_iterator found = 
    std::find_if(vec.begin(), vec.end(),
                 MyEqualsByVal<std::string*>(s2)); // OK, will find "foo"

3 个答案:

答案 0 :(得分:6)

find不能重载以获取一元谓词而不是值,因为它是一个无约束的模板参数。因此,如果您调用find(first, last, my_predicate),则是否希望在范围的每个成员上评估谓词,或者是否要查找与谓词本身相等的范围成员(它可以是一系列谓词,对于标准库的所有设计者都知道或关心,或者迭代器的value_type可以转换为谓词类型和argument_type)。因此,find_if需要使用单独的名称。

除了搜索的值之外,

find可能已被重载以获取可选的二元谓词。但是,正如你所做的那样,在仿函数中捕获值是一种标准技术,我认为这不会是一个巨大的收获:它肯定是绝对必要的,因为你始终可以用find_if获得相同的结果。

如果你得到了你想要的find,你仍然需要编写一个仿函数(或使用boost),因为<functional>不包含任何取消引用指针的东西。但是,您的仿函数作为二元谓词会更简单,或者您可以使用函数指针,因此它是一个适度的增益。所以我不知道为什么没有提供。鉴于copy_if惨败,我不确定假设总有很好的理由没有可用的算法: - )

答案 1 :(得分:2)

由于T是指针,因此您也可以在函数对象中存储指针的副本。

除此之外,它就是这样做的,并没有更多的东西。

顺便说一句,将裸指针存放在容器中并不是一个好主意,除非你非常小心地确保异常安全,这几乎总是比它的价值更麻烦。

答案 2 :(得分:0)

这正是find_if的用途 - 它需要一个谓词来比较元素。