5

我有一个类 tPoint 将实现具有不同的基本类型,所以

template<typename T>class tPoint{
   T x;
   T y;
public:
   void Set(T ix, T iy){x=ix;y=iy;}
};

当类型 T 是 int, 时tPoint<int>,我想要一个特殊的 Set(float, float) 以便在分配之前对值进行四舍五入。

我认为通过专业化我可以:

template<> void tPoint<int>::Set(float ix,float iy){x=ix+.5; y=iy+.5;}

这样编译器就会抱怨类定义中没有匹配的函数。

但是如果我在类 Set(float,float) 中声明,那么它说已经定义了(当它编译为 T =float 时)

我希望我说清楚了,什么是干净的方法,或者我做错了什么?谢谢!

4

5 回答 5

5

您需要专门化该课程,如下所示:

template<> class tPoint<int>{
   int x;
   int y;
public:
   void Set(int ix, int iy){x=ix;y=iy;}
   void Set(float ix, float iy){x = ix+0.5; y = iy+0.5;}
};
于 2011-02-26T17:49:06.017 回答
3

您面临的问题与T代表intfloat

如果您查看模板类定义,您会注意到该部分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和未使用的分支;)

于 2011-02-26T18:34:40.267 回答
0

当实例化为浮点数时,使用 boost enable_if 来防止浮点版本。

于 2011-02-26T17:55:12.437 回答
0

你最好的选择是:

template<typename T>class tPoint{
   T x;
   T y;
public:
   void Set(T ix, T iy) { set_impl(boost::type<T>(), x, y); }
private:
   void set_impl(boost::type<int>, float ...);
   template<typename U>
   void set_impl(boost::type<U>, T ...);
};
于 2011-02-26T17:56:48.767 回答
0

尽量不要在类中提供 Set() 的默认实现。这样,更容易专门针对浮动。

于 2011-02-26T17:57:16.200 回答