看了很多模板的书一直没有实践, 最近把原来的基类的代码用模板改了下
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; }
比如上面的例子,我们现在不仅要做加法还要做乘法运算。
// 加法 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...