我有以下类定义:
template <typename T>
class MyBox {
public:
MyBox(T value) { _value = value; }
operator T() const { return _value; }
private:
T _value;
};
typedef MyBox<int> MyInt;
typedef MyBox<std::string> MyString;
当我尝试在我的typedef上使用运算符时
bool first = MyInt(1) == MyInt(1); // works
bool second = std::string(MyString("a")) == std::string(MyString("a")); //works
bool third = MyString("a") == MyString("a"); // does not compile
编译器抱怨第三次比较
没有运算符“==”匹配这些操作数。操作数类型是:MyString == MyString
并且这种情况发生在任何其他非原始拳击中(例如MyBox<float>
有效但MyBox<std::map<int,int> >
无效。为什么会这样?
这一点对我来说尤其不清楚,因为第一次和第二次比较使用了operator T()
- 为什么不能自动为MyString
完成?
UPDATE:除了为每个非原始模板提供特定的运算符之外,还有一个简单的解决方案吗?如何处理MyString("a") == std::string("a")
?
答案 0 :(得分:3)
为什么它适用于内置类型但不适用于自定义类型的原因在以下SO问题中得到了回答:using user-defined conversions with implicit conversions in comparisons。简而言之,这是因为模板推导类型不会发生类型转换。虽然operator==
的内置int
不是模板(因此可以在使用MyBox<int>
时使用类型转换找到),operator==
用于std::string
是一个模板。
但是,上面提到的问题没有详细说明如何解决这个问题。方法如下:添加以下免费功能
template<class T>
bool operator==(const MyBox<T>& lhs, const MyBox<T>& rhs) {
return static_cast<const T&>(lhs) == static_cast<const T&>(rhs);
}
template<class T>
bool operator==(const MyBox<T>& lhs, const T& rhs) {
return static_cast<const T&>(lhs) == rhs;
}
template<class T>
bool operator==(const T& lhs, const MyBox<T>& rhs) {
return lhs == static_cast<const T&>(rhs);
}