使用模板时C ++算术运算符重载 - 自动转换

时间:2013-06-25 07:14:04

标签: c++ templates

当我为我的短向量类实现vector-op-scalar运算符时遇到了一个问题。代码列表如下:

template<class T>
class Vec3
{
    Vec3& operator*=( const T& rhs );
};
template<class T>
Vec3<T> operator*( const Vec3<T>& lhs, const T& rhs );
Vec3<float> a;
a*=3; // right 
a*3; // wrong

好吧,我真的很惊讶,对于运算符* =,正如我所料,常量整数3可以自动转换为float,但对于运算符*,它不能,并导致下面的编译错误列表:

  

错误C2782:'Vec3运算符*(const Vec3&amp;,T)':模板参数'T'不明确

     

main.cpp(162):参见'operator *'的声明可以是'int'或'float'

我对此感到困惑,并且不知道为什么会这样。

3 个答案:

答案 0 :(得分:1)

template<class T>
Vec3<T> operator*( const Vec3<T>& lhs, const T& rhs );

如果lhs是Vec3而rhs是一个int,编译器只会混淆它应该使用的模板化函数的版本(int-或float-版本)。 尝试写a * 3.0f。 您还可以将operator *直接添加到您的类中,这样编译器就会调用类型Vec3<float>上的方法,因此您的星号右侧的类型始终会转换为float。

答案 1 :(得分:0)

在第一个(*=)中,T模板参数已在变量decleration处解析,因此该函数已使用签名Vec3& operator*=( const float& rhs )创建,现在可以使用int

在第二种情况下,编译器现在尝试根据模板参数创建适当的函数,它有两种不同的类型 - floatlhs int rhs - 两者都是相同的模板参数,因此不知道如何创建函数签名。

答案 2 :(得分:0)

当您调用成员运算符时,编译器已知该签名

Vec3& operator*=( const float& rhs );

需要在intfloat之间执行隐式转换。没问题。

当您调用模板operator*时,它需要推断 T,并且只有在{每次使用{时可以推断为相同类型时才能成功签名中的{1}}。此处不执行类型转换。编译器看到它是T一次而float另一次,所以它出错了。

一种解决方法是使用两个不同的模板参数声明自由运算符,并将实际工作委托给其中的成员运算符。

int

现在编译器可以在参数之间进行类型转换,如果不可能,则会出错。