您面临的问题与T
代表int
或float
。
如果您查看模板类定义,您会注意到该部分T
之后出现的相同内容也作为方法的参数出现。typename
template
Set
这意味着当您谈到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
和未使用的分支;)