1

我在通过重写的相等运算符比较同一接口的模板实现时遇到问题。

Interface* ptr1 = ...; Interface* ptr2 = ...;
*ptr1 == *ptr2;

我想出的唯一解决方案是强制只比较相同实现的对象并像这样实现比较:

class Interface {
public:
    virtual ~Interface() {}
    virtual bool operator==(const Interface&) const = 0;
};

template <typename T> class Impl : public Interface {
public:
    bool operator==(const Interface& rhs) const {
        assert(typeid(rhs) == typeid(const Impl&));
        const Impl& rhsRef = static_cast<const Impl&>(rhs);
        // ...
    }
};

这个解决方案的问题是它对我的目的来说太有限了——我希望能够比较不同的实现。如果实现的数量有限,则可以使用双分派模式。但在我的例子中,Impl 是一个模板,所以双重分派是不可能的,因为它需要一个虚函数模板:

// This obviously doesn't work.

class Interface {
public:
    virtual ~Interface() {}
    virtual bool operator==(const Interface&) const = 0;
    template <typename T2> virtual bool operator==(const Impl<T2>&) const = 0;
};

template <typename T> class Impl : public Interface {
public:
    bool operator==(const Interface& rhs) const {
        return rhs == *this;
    }
    template <typename T2> bool operator==(const Impl<T2>& rhs) const {
        // ...
    }
};

有什么解决办法吗?我需要这个来编写可以包装任何 STL 迭代器的 AnyIterator 类。但是我无法比较 AnyIterators,如果它们被包裹在不同的类型中,例如 iterator 和 const_iterator:

std::list<int>::iterator it1 = ...; std::list<int>::const_iterator it2 = ...;
AnyIterator<const int> myIter1 = it1; AnyIterator<const int> myIter2 = it2;
it1 == it2;         // This works perfectly.
myIter1 == myIter2; // This doesn't work!
4

2 回答 2

1

我认为这里的问题是operator==在你的界面中,根本没有任何意义。如果您想为您的实现提供比较,那是另一回事,例如:

bool operator==(const Impl<T>& other) const {
    // ...
}

不过,即使在这种情况下,我通常也不鼓励创建运算符重载。相反,提供访问器来获取某人可能想要比较的相关属性,并将其留给使用您的代码的人来创建他们想要进行的比较。

对于这些任意比较,您有特定的用例吗?

于 2011-02-06T05:42:05.520 回答
0

您可以使用dynamic_cast代替static_cast并检查std::bad_cast(在这种情况下总是返回 false)。您可以使用指针 dynamic_cast 而不是引用强制转换,在这种情况下,您只需要检查 NULL 而不是捕获异常。

于 2011-02-06T06:31:33.560 回答