【问题标题】:How to std::find using a Compare object?如何使用比较对象 std::find?
【发布时间】:2010-04-16 23:35:15
【问题描述】:

我对@9​​87654321@的界面感到困惑。为什么不使用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"

【问题讨论】:

    标签: c++ stl vector find compare


    【解决方案1】:

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

    find 可能已被重载以采用可选的二进制谓词,除了搜索的值。但是,正如您所做的那样,在函子中捕获值是一种标准技术,我认为这不会是一个巨大的收获:它当然从来没有必要,因为您总是可以使用find_if 获得相同的结果。

    如果你得到了你想要的find,你仍然需要编写一个仿函数(或使用boost),因为&lt;functional&gt; 不包含任何取消引用指针的内容。不过,作为二元谓词,您的仿函数会更简单一些,或者您可以使用函数指针,所以这将是一个适度的收益。所以我不知道为什么不提供这个。鉴于copy_if 惨败,我不确定假设算法不可用总是有充分的理由有多大价值:-)

    【讨论】:

    • @dehmann:唯一的问题是它不在标准中。它基本上是由于编辑事故而被遗漏的。
    【解决方案2】:

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

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

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

    【讨论】:

    • 而且...我完全错过了问题的前半部分...哎呀。不过,史蒂夫·杰索普的回答比我能解释的要好。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 2022-11-21
      相关资源
      最近更新 更多