首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将operator==重载为带有模板化参数的自由函数的语法是什么?

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

Stack Overflow用户
提问于 2011-06-07 03:51:58
回答 3查看 4K关注 0票数 5

我有一组多态类,例如:

代码语言:javascript
运行
复制
class Apple {};
class Red : public Apple {};
class Green : public Apple {};

和比较它们的自由函数:

代码语言:javascript
运行
复制
bool operator==(const Apple&, const Apple&);
bool operator< (const Apple&, const Apple&);

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

代码语言:javascript
运行
复制
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==开发一个免费函数,如下所示:

代码语言:javascript
运行
复制
template<typename Cat>
bool operator==(const Copy<Cat>& copy, const Cat& e) {
    return *copy == e;
}

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

代码语言:javascript
运行
复制
Red red;
Copy<Apple> redCopy = red;
Copy<Apple> redCopy2 = redCopy;
assert(redCopy == Red());

但是编译器告诉我

代码语言:javascript
运行
复制
../src/main.cpp:91: error: no match for ‘operator==’ in ‘redCopy == Red()’

如何让它识别上面的operator==?我怀疑答案可能是在某个地方添加一些隐式转换代码,但我不确定该怎么做。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-07 04:02:25

您的模板被声明为

代码语言:javascript
运行
复制
template <typename Cat>
bool operator==(const Copy<Cat>& copy, const Cat& e)

这与redCopy == Red()不匹配,因为Red()的类型是Red,所以编译器将Red推断为第二个参数的类型,即Cat = Red,但是它期望第一个参数的类型为Copy<Red>,但事实并非如此(redCopy的类型为Copy<Apple>)。

你真正想表达的东西是这样的

代码语言:javascript
运行
复制
template <typename Cat>
bool operator==(const Copy<Cat>& copy, const something-that-derives-from-Cat& e)

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

代码语言:javascript
运行
复制
template <typename Cat, typename DerivedFromCat>
bool operator==(const Copy<Cat>& copy, const DerivedFromCat& e)

当然,这并不能让编译器强制说明DerivedFromCat实际上是从Cat派生的。如果你想要这样,你可以使用boost::enable_if

代码语言:javascript
运行
复制
template <typename Cat, typename DerivedFromCat>
typename enable_if<is_base_of<Cat, DerivedFromCat>, bool>::type
operator==(const Copy<Cat>&, const DerivedFromCat& e)

但这可能有点过头了.

票数 9
EN

Stack Overflow用户

发布于 2011-06-07 04:03:23

但是..。你期望它如何工作?您声明了一个模板运算符

代码语言:javascript
运行
复制
template<typename Cat>
bool operator==(const Copy<Cat>& copy, const Cat& e)

这意味着RHS上的类型与LHS上的模板参数相同(在两种情况下都是Cat)。但是您希望它在以下情况下被调用:

代码语言:javascript
运行
复制
redCopy == Red()

其中redCopyCopy<Apple>。多么?

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

如果您将redCopy声明为

代码语言:javascript
运行
复制
Copy<Red> redCopy;

然后你的操作员就可以工作了。或者如果你这样做了

代码语言:javascript
运行
复制
redCopy == Apple()

你的操作员也可以工作。但是当你混合你的原始类型时

代码语言:javascript
运行
复制
Copy<Apple> redCopy;
redCopy == Red();

它根本不能工作。在这种情况下,您的意图是什么?

票数 3
EN

Stack Overflow用户

发布于 2011-06-07 04:30:08

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

代码语言:javascript
运行
复制
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==将按预期工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6257265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档