模板类的二进制运算符不能解决隐式转换 [英] Binary Operator for Template Class Doesn't Resolve Implicit Conversion

查看:123
本文介绍了模板类的二进制运算符不能解决隐式转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下类,其中第一个是模板化的.两者都应保留一个数值.

Consider the following classes, where the first is templated. Both are meant to hold a numeric value.

template<typename T>
struct foo
{
    foo(T val) : val{ val } {}
    T val;
};

struct bar
{
    bar(double val) : val{ val } {}
    double val;
};

我想定义一种将这些类加在一起以获得具有不同值的新类的方法.

I want to define a way to add these classes together to get a new one with a different value.

template<typename T>
foo<T> operator+(foo<T> a, foo<T> b)
{
    return foo<T>(a.val + b.val);
}

bar operator+(bar a, bar b)
{
    return bar(a.val + b.val);
}

当我使用这些运算符进行隐式转换时,使用类型为foo的对象的运算符不会对double值使用隐式转换来应用我的重载运算符,即使它可以对非模板类执行此操作.结果是没有运算符匹配该表达式中的类型.

When I use these operators with implicit conversion, the operator using object of type foo doesn't use the implicit conversion on the double value to apply my overloaded operator, even though it can do it for the non-template class. The result is that there is no operator matching the types in that expression.

int main()
{
    foo<double> foo_value(11.0);
    bar bar_value(11.0);

    foo<double> ev1 = foo_value + 1.0; // no operator matches these operands
    bar ev2 = bar_value + 1.0;
}

是否必须首先显式实例化运算符?如果是这样,a)看起来如何,b)如果在初始化类型为foo<double>的对象时可以完成实例化,为什么不隐式完成该实例化呢?

Does the operator have to be explicitly instantiated first? If so, a) how does that look like, and b) why isn't the instantiation done implicitly, if it can be done when initializing an object of type foo<double>?

如果标准在不显式将1.0强制转换为类型foo<double>的值的情况下不支持任何类型的分辨率,则我认为唯一的另一种可能性是为要使用的每种类型定义运算符重载(对于都是lhs和rhs)?

If the standard doesn't support any sort of resolution without explicitly casting 1.0 to a value of type foo<double>, I presume the only other possibility is defining operator overloads for each type I want to use like that (for both lhs and rhs)?

推荐答案

关于模板,您要记住的事情是模板将为您进行转换.他们所做的只是尝试找出事物的类型,如果这些事物与模板参数匹配,那么它将标记出函数并调用它.

The thing you have to remember about templates is that they will not do a conversion for you. All they do is try and figure out the types things are, and if that jives with template parameters, then it will stamp out the function and call it.

如果您这样做的话

foo_value + 1.0

编译器运行正常,让我们看看是否有任何operator +对此适用.找到

the compiler goes okay, lets see if we have any operator + that will work for this. It finds

template<typename T>
foo<T> operator+(foo<T> a, foo<T> b)
{
    return foo<T>(a.val + b.val);
}

,然后尝试找出T是什么,以便可以标记出具体功能.它查看foo_value,看到它是一个foo<double>,因此它说对于第一个参数T需要是一个double.然后它查看1.0并正常,我有一个double,那就是您遇到问题时.编译器无法推断b应该是T的原因,因为它期望使用foo<some_type>,但是却得到了double.因为它不能推导类型,所以您的代码无法编译.

and then it tries to figure out what T is so it can stamp out a concrete function. It looks at foo_value, sees it is a foo<double> so it says for the first parameter T needs to be a double. Then it looks at 1.0 and goes okay, I have a double and that is when you run into a problem. The compiler can't deduce what T should be for b because it expects a foo<some_type>, but got a double instead. Because it can't deduce a type, your code fails to compile.

要获得您想要的行为,您需要添加

In order to get the behavior you want you would need to add

template<typename T>
foo<T> operator+(foo<T> a, T b)
{
    return foo<T>(a.val + b);
}

您可以将T添加到foo<T>或更好的

Which lets you add a T to a foo<T>, or better yet

template<typename T, typename U>
foo<T> operator+(foo<T> a, U b)
{
    return foo<T>(a.val + b);
}

您可以在其中添加任何内容到foo<T>(例如,foo<double> + int在第一个版本不允许的情况下)

Which lets you add anything to a foo<T> (foo<double> + int for instance where the first version would not allow that)

这篇关于模板类的二进制运算符不能解决隐式转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆