看了很多模板的书一直没有实践, 最近把原来的基类的代码用模板改了下
template<typename T> class Rect{
friend class RectCmp<T>;
public:
Rect();
...
private:
union{
struct{
T x1;
T y1;
T x2;
T y2;
};
T elems[4];
};
};
template<typename T>Rect<T>::Rect(){ ... }
基本方法如此,很简单, 但是使用模板遇到一个很麻烦的问题,就是和接口的封装冲突比较大,因为他要求把实现和定义都写在同一个文件里面,这也是为什么模板函数都要inline的原因,(export 关键字有一些负作用,前途未卜),这样对接口的封装影响比较大。
下面介绍一下模板的trait 和 policy 类
trait 就是对另一种类型的封装, 比如用trait来解决一个加法溢出的问题
// 用int来封装char,避免溢出
template<>
class AccumulationTraits<char>{
public:
typdef int AccT;
static AccT const zero() { return 0 }; // 定义 zero, static可以节省内存
};
// 做加法运算
template<typename T> inline typename AccumulationTraits<T>::AccT accum(T const* beg, T const* end){
typedef typename AccumulationTraits<T>::AccT Acct;
AccT total=AccumulationTraits<T>::zero();
while (beg!=end){
total += *beg;
++beg;
}
return total;
}
policy,就是采用的一种把算法当成对象的方法,所以有很多基于policy的design pattern的实现。
比如上面的例子,我们现在不仅要做加法还要做乘法运算。
// 加法
class SumPolicy{
public:
template<typename T1, typename T2>
static void accumulate(T1& total, T2 const& value){ total+=value;}
};
// 乘法
class MultPolicy{
public:
template<typename T1, typename T2>
static void accumulate(T1& total, T2 const& value) { total*=value; }
};
// policy的调用
template<typename T, typename Policy, typename Traits>
class Accum{
public:
typedef typename Traits::AccT AccT;
static AccT accum(T const* beg, T const* end){
AccT total=Traits::zero();
while(beg!=end){
Policy::accumulate(total, *beg);
++beg;
}
return total;
}
};
// 使用:total = Accum<char, MultPolicy, AccumulationTraits<char> >::accum(&num[0], &num[5]);
小技巧:
模板借助sizeof 可以用来显示数组的长度
template <typename T, int N>class A{
T a[N];
};
sizeof(A<float, 100>);
小问题:
template 到 template 的 typedef 不支持,不小的C++11对此怎么说。
... to be continued...