Operator== 抽象 class 和 shared_ptr 的重载

Operator== overloading of an abstract class and shared_ptr

我想在摘要 class 的 shared_ptr 列表中使用 std::find,但出现错误。有没有办法通过在 std::find 中取消引用来比较两个 shared_ptr

是否有可能交一个朋友 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
    }
};

Error C2679 binary '==': no operator found which takes a right-hand operand of type 'const Point' (or there is no acceptable conversion)

注意:Point已经有operator==

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,当使用 find(l.begin(), l.end(), p) 时,它会转换为 shared_ptr<A> == Point。由于它将使用 shared_ptr<A>::operator==,因此您将使用 std::find_if 并编写自定义比较 function/functor 来比较这两种类型并将其传递给 find

您可以在以下位置了解有关函子的更多信息:C++ Functors - and their uses

问题:

find() 旨在在迭代器范围内找到一个精确的 value

您定义了一个 operator== 来比较 APoint。但是您的列表不包含 A 个对象,而是指向 A 个对象的共享指针。不幸的是,将共享指针与 Point 进行比较并没有定义。这种不匹配会导致您报告的错误。

解决方案:

一个简单的解决方案是使用 find_if() 而不是 find():它不寻找精确的值,而是寻找谓词变为真:

   const auto & f = find_if(l.begin(), l.end(),[p](shared_ptr<A> &a){ return *a==p; });