将operator ==重载为带有模板化参数的自由函数的语法是什么?

时间:2011-06-06 19:51:58

标签: c++ templates operator-overloading non-member-functions

我有一组多态类,例如:

class Apple {};
class Red : public Apple {};
class Green : public Apple {};

比较它们的免费功能:

bool operator==(const Apple&, const Apple&);
bool operator< (const Apple&, const Apple&);

我正在设计一个可复制的包装类,它允许我使用类RedGreen作为STL映射中的键,同时保留它们的多态行为。

template<typename Cat>
class Copy
{
public:
    Copy(const Cat& inCat) : type(inCat.clone()) {}
    ~Copy() { delete type; }
    Cat* operator->() { return type; }
    Cat& operator*() { return *type; }
private:
    Copy() : type(0) {}
    Cat* type;
};

我希望Copy<Apples>类型与Apples尽可能互换。还有一些函数我必须添加到上面的Copy类中,但是现在我正在为operator==开发一个免费函数,如下所示:

template<typename Cat>
bool operator==(const Copy<Cat>& copy, const Cat& e) {
    return *copy == e;
}

以下是我的测试代码的一部分:

Red red;
Copy<Apple> redCopy = red;
Copy<Apple> redCopy2 = redCopy;
assert(redCopy == Red());

但编译器告诉我

../src/main.cpp:91: error: no match for ‘operator==’ in ‘redCopy == Red()’

如何让它识别我的算子==以上?我怀疑答案可能是在某处添加一些隐式转换代码,但我不知道该怎么做。

3 个答案:

答案 0 :(得分:8)

您的模板声明为

template <typename Cat>
bool operator==(const Copy<Cat>& copy, const Cat& e)

这与redCopy == Red()不匹配,因为Red()的类型为Red,因此编译器会将Red推断为第二个参数的类型,即{{1} } = Cat,但是它要求第一个参数的类型为Red,而不是Copy<Red>的类型为redCopy)。

你真正想要表达的是

Copy<Apple>

最简单的方法是添加第二个模板参数:

template <typename Cat>
bool operator==(const Copy<Cat>& copy, const something-that-derives-from-Cat& e)

当然,这并没有让编译器强制DerivedFromCat实际上是从Cat派生的。如果您需要,可以使用template <typename Cat, typename DerivedFromCat> bool operator==(const Copy<Cat>& copy, const DerivedFromCat& e)

boost::enable_if

但这可能有点矫枉过正......

答案 1 :(得分:3)

但是......你怎么期望它起作用?您声明了模板运算符

template<typename Cat>
bool operator==(const Copy<Cat>& copy, const Cat& e)

意味着RHS上的类型与LHS上的模板参数相同(在两种情况下都为Cat)。但是你希望在

的情况下调用它
redCopy == Red()

其中redCopyCopy<Apple>。怎么样?

注意:redCopy的模板参数为Apple,而不是Red。您的模板运算符根本无法匹配这些类型。

如果您将redCopy声明为

Copy<Red> redCopy;
然后你的运营商会工作。或者如果你做了

redCopy == Apple()

您的运营商也会工作。但是当你混合类似原始的

Copy<Apple> redCopy;
redCopy == Red();
它根本无法工作。在这种情况下你的意图是什么?

答案 2 :(得分:3)

@ HighCommander4解释了这里的错误。另一种解决方案是禁用operator==的第二个参数的扣除。然后,仅根据== - 运算符的第一个参数推导出第二个参数的类型:

template<typename T> struct identity { typedef T type; };

template<typename Cat>
bool operator==(const Copy<Cat>& copy, typename identity<Cat>::type const& e) {
    return *copy == e;
}

如果你这样做,那么Cat代表什么类型并不矛盾,operator==将按预期工作。