用于特定模板专门化的重载成员函数
我有一个类 tPoint ,它将实现为具有不同的基类型,因此
template<typename T>class tPoint{
T x;
T y;
public:
void Set(T ix, T iy){x=ix;y=iy;}
};
当类型 T 为 int 时,tPoint
,我想要一个特殊的 Set(float, float),以便我可以在之前对值进行四舍五入分配。
我认为通过专业化我可以:
template<> void tPoint<int>::Set(float ix,float iy){x=ix+.5; y=iy+.5;}
这样编译器会抱怨类定义中没有匹配的函数。
但是如果我在类 Set(float,float) 中声明,那么它会说已经定义了(当它编译为 T =float 时)
我希望我自己说清楚,什么是一个干净的方法,否则我做错了什么?谢谢!
I have a class tPoint that would be implemented having different base types so
template<typename T>class tPoint{
T x;
T y;
public:
void Set(T ix, T iy){x=ix;y=iy;}
};
When the type T is int, tPoint<int>
, I want a special Set(float, float) so I can round the values before assignation.
I thought that with specialisation I could:
template<> void tPoint<int>::Set(float ix,float iy){x=ix+.5; y=iy+.5;}
This way the compiler complains that there's no matching function in the class definition.
But if I declare in the class Set(float,float) then it says that's already defined (when it compiles for T =float)
I hope I made myself clear, what would be a clean approach to this or I'm doing something wrong? thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要专门化该类,如下所示:
You need to specialize the class, like this:
您面临的问题与
T
代表int
或float
有关。如果您查看模板类定义,您会注意到
template
部分中typename
后面出现的相同T
也显示为参数到Set
方法。这意味着当您谈到
Point
时,只定义了一个Set
方法,该方法需要两个int.每个不同的
Point
都会有自己的Set(T,T)
方法。如果您希望使用不同的
Set
方法,那么您需要在模板类中声明一个模板Set
,这样做是这样的:注意我如何必须选择不同的模板参数名称。
为了解决您的问题,您可以为
float
引入另一种方法,但是您必须为double
和long double
引入另一种方法code>...很快就会变得困难。最简单的解决方案是暴力破解:
对于 int 和 al 来说,它几乎没有用,但有效。对于浮点,我们使用可用的更大浮点类型以避免丢失精度,然后执行舍入。
显然,如果我们突然想要一个 Point,它就不太有效,因此我们需要一个基于类型特征的更智能的解决方案。
std::numeric_limits
类有一个is_integer
,它精确地确定我们是否正在处理整数类型。我知道使用
if
来处理可以在编译时确定的东西似乎很愚蠢......但不用担心,编译器足够聪明,可以做计算它在编译时被删除并完全优化掉if
和未使用的分支;)The issue you're facing has to do with
T
standing either forint
orfloat
.If you look at the template class definition, you'll remark that the same
T
that appears aftertypename
in thetemplate
part also appears as parameter to theSet
method.This means that when you speak of
Point<int>
then there is only oneSet
method defined, which takes twoint
. And each differentPoint<T>
will have its ownSet(T,T)
method.If you wish for a different
Set
method, then you need to declare a templateSet
within the template class, this is done like so:Note how I had to chose a different template parameter name.
In order to solve your problem, you could introduce another method, for
float
, but then you'd have to have another fordouble
, andlong double
... it's soon going to become difficult.The simplest solution, is to go bruteforce:
For
int
and al, it's mostly useless but works. For floating points, we use the bigger floating point type available to avoid losing precision, and then perform the rounding.Obviously, it does not quite work if suddenly we want a
Point<float>
, therefore we need a smarter solution, based on type traits. The classstd::numeric_limits<T>
has ais_integer
which precises whether or not we are dealing with an integral type.I know it seems stupid to use a
if
for something that could be determined at compile-time... but don't worry, the compiler is smart enough to do figure it out at compile-time and optimize away theif
and the unused branch altogether ;)使用 boost enable_if 来防止在使用 float 实例化时使用 float 版本。
Use boost enable_if to prevent the float version when instanciated with float.
你最好的选择是:
your best bet is:
尽量不要在类中提供 Set() 的默认实现。这样,就更容易专注于浮动。
Try not to provide the default implementation of Set() inside the class. That way, it's easier to specialize for float.