我想在std::find
抽象类的列表中使用shared_ptr
,但是我收到了错误。有没有办法比较两个shared_ptr
std::find
中取消引用它们?
是否有可能让朋友operator==
超载shared_ptr<A>
?
最小例子:
#include "point.h"
#include <list>
#include <algorithm>
#include <memory>
using namespace std;
class A {
protected:
Point loc;
public:
virtual void foo() = 0;
virtual bool operator==(const Point& rhs) const = 0;
};
class B: public A {
virtual void foo() override{}
virtual bool operator==(const Point& rhs) const override {
return rhs == loc;
}
};
class C {
list<shared_ptr<A>> l;
void bar(Point & p) {
const auto & f = find(l.begin(), l.end(), p); //<-- error is from here
}
};
错误C2679二进制'==':找不到哪个运算符采用'const Point'类型的右手操作数(或者没有可接受的转换)
注意:Point
已有operator==
。
答案 0 :(得分:5)
find()
旨在在迭代器范围内找到一个精确的值。
您已定义operator==
以将A
与Point
进行比较。但是您的列表不包含A
个对象,而是共享指向A
个对象的指针。不幸的是,将共享指针与Point进行比较并不是定义的。这种不匹配会导致您报告的错误。
一个简单的解决方案是使用 find_if()
而不是find()
:它不会寻找精确的值,而是让谓词变为真:
const auto & f = find_if(l.begin(), l.end(),[p](shared_ptr<A> &a){ return *a==p; });
答案 1 :(得分:1)
std::find
可以实现为
template<class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value)
{
for (; first != last; ++first) {
if (*first == value) {
return first;
}
}
return last;
}
正如您所看到的那样,在使用*first == value
时,会将shared_ptr<A> == Point
与find(l.begin(), l.end(), p)
进行比较。由于它将使用shared_ptr<A>::operator==
,您将使用std::find_if
并编写自定义比较函数/仿函数,可以比较这两种类型并将其传递给find