特定模板特化的重载成员函数

时间:2011-02-26 17:44:15

标签: c++ templates specialization

我有一个可以实现不同基类型的类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编译时)

我希望自己清楚明白,对此采取什么干净措施或者我做错了什么?谢谢!

5 个答案:

答案 0 :(得分: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;}
};

答案 1 :(得分:3)

您遇到的问题与T代表intfloat有关。

如果您查看模板类定义,您会注意到T部分中typename之后显示的template也会显示为Set的参数方法。

这意味着当您谈到Point<int>时,只定义了一个 Set方法,这需要两个int。每个不同的Point<T>都有自己的Set(T,T)方法。

如果您希望使用其他Set方法,则需要在模板类中声明模板Set,这样做:

template <typename T>
class Point
{
public:
  template <typename Num>
  void Set(Num x, Num y);
};

请注意我必须选择不同的模板参数名称。


为了解决您的问题,您可以为float引入另一种方法,但是您必须为doublelong 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;
  }
  }
}

我知道将if用于可以在编译时确定的东西似乎很愚蠢...但不要担心,编译器足够智能数字它在编译时出来并完全取消if和未使用的分支;)

答案 2 :(得分:0)

使用boost enable_if来防止浮动版本与float一起实现。

答案 3 :(得分: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 ...);
};

答案 4 :(得分:0)

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

相关问题