您面临的问题与T代表int或float。
如果您查看模板类定义,您会注意到该部分T之后出现的相同内容也作为方法的参数出现。typenametemplateSet
这意味着当您谈到Point<int>then 时,只定义了一个 Set方法,它需要两个int. 每个不同Point<T>的人都有自己的Set(T,T)方法。
如果您希望使用不同的Set方法,那么您需要Set在模板类中声明一个模板,这样做是这样的:
template <typename T>
class Point
{
public:
template <typename Num>
void Set(Num x, Num y);
};
请注意我必须如何选择不同的模板参数名称。
为了解决您的问题,您可以引入另一种方法 for float,但是您必须使用另一种方法 for double,并且long double...很快就会变得困难。
最简单的解决方案是暴力破解:
template <typename Integral>
template <typename Num>
void Point<Integral>::Set(Num x, Num y)
{
this->x = long double(x) + 0.5;
this->y = long double(y) + 0.5;
}
对于int和 al,它大多是无用的,但有效。对于浮点,我们使用更大的浮点类型来避免丢失精度,然后进行舍入。
显然,如果我们突然想要一个 ,它就不太好用了Point<float>,因此我们需要一个基于类型特征的更智能的解决方案。该类std::numeric_limits<T>有一个is_integer精确的,我们是否正在处理一个整数类型。
template <typename T>
template <typename Num>
void Point<T>::Set(Num x, Num y)
{
if (std::numeric_limits<T>::is_integer &&
!std::numeric_limits<Num>::is_integer)
{
this->x = x + 0.5;
this->y = y + 0.5;
}
else
{
this->x = x;
this->y = y;
}
}
}
我知道将 a 用于可以在编译时确定的东西似乎很愚蠢if......但别担心,编译器足够聪明,可以在编译时找出它并完全优化掉if和未使用的分支;)