当我为我的短向量类实现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'
我对此感到困惑,并且不知道为什么会这样。
答案 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
。
在第二种情况下,编译器现在尝试根据模板参数创建适当的函数,它有两种不同的类型 - float
和lhs
int
rhs
- 两者都是相同的模板参数,因此不知道如何创建函数签名。
答案 2 :(得分:0)
当您调用成员运算符时,编译器已知该签名
Vec3& operator*=( const float& rhs );
需要在int
和float
之间执行隐式转换。没问题。
当您调用模板operator*
时,它需要推断 T
,并且只有在{每次使用{时可以推断为相同类型时才能成功签名中的{1}}。此处不执行类型转换。编译器看到它是T
一次而float
另一次,所以它出错了。
一种解决方法是使用两个不同的模板参数声明自由运算符,并将实际工作委托给其中的成员运算符。
int
现在编译器可以在参数之间进行类型转换,如果不可能,则会出错。