类型擦除和互操作性:C ++中的虚拟二进制运算符问题

时间:2011-02-06 05:32:49

标签: c++ type-erasure comparison-operators

我在通过覆盖等式运算符比较同一接口的模板实现时遇到了问题。

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 {
        // ...
    }
};

有什么解决方案吗?我需要这个来编写AnyIterator类,它可以包装任何STL迭代器。但我无法比较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!

2 个答案:

答案 0 :(得分:1)

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

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

尽管如此,我通常不鼓励创建运算符重载;相反,提供访问器以获取某人可能想要比较的相关属性,并将其留给使用您的代码的任何人创建他们想要进行的比较。

您是否有针对这些任意比较的特定用例?

答案 1 :(得分:0)

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