将与参数无关的代码抽离templates

关键概念一:代码膨胀

在使用模板函数的时候可能会因为实例化出过多的版本而出现代码冗余的现象。

实例:

1 template <typename T, std::size_t n>
2 class SquareMatrix{
3 public:
4     ...
5     void invert(); //求逆矩阵
6 };

以上代码功能简单:实现一个矩阵求逆。其中T是矩阵中的类型参数, n是矩阵的维数,比如n==5代表一个5*5的矩阵

其中T是一个类型模板参数, n是一个非类型模板参数。

这个代码引起膨胀的原因是: 不仅会针对不同的类型实例化版本,还会对不同的大小实例化版本,这样的话实例化出来的版本将是海量的。

改进方法:

将求逆的过程独立出来,将矩阵的维数当成一个参数而不是模板参数。

例程:

 1 template <typename T, std::size_t n>
 2 class SquareMatrix{
 3 public:
 4     ...
 5     void invert(); //求逆矩阵
 6 };
 7 template<typename T>
 8 class SquareMatrixBase{
 9 protected:
10     SquareMatrixBase(std::size_t n, T* pMem)
11         :size(n), pData(pMem){}
12     void setDataPtr(T* ptr){ pData = ptr; }
13     ...
14     void invert(std::size_t matrixSize);   //将尺寸当成参数  这样就只针对类型特例化而不针对大小特例化
15     ...
16 private:
17     std::size_t size;
18     T* pData;
19 };
20 template<typename T, std::size_t n>
21 class SquareMatrix : private SquareMatrixBase<T>{
22 private:
23     using SquareMatrixBase<T>::invert;  //避免遮掩base版本
24 public:
25     SquareMatrix() :SquareMatrixBase<T>(n, 0),
26         pData(new T[n*n]);
27     {this->setDataPtr(pData.get()); }
28     ...
29     void invert(){ this->invert(n); }
30 private:
31     boost::scoped_array<T> pData;
32 };

以上的代码主要有以下特点:

1.将求逆模板和矩阵的管理模版分开,矩阵管理模版继承求逆的模板这样同一类型不同维数的管理模版只会继承同一个求逆的模板。

2.管理模版里面并没有实际的函数它单纯的调用函数不会引起代码膨胀。

关于以上膨胀与不膨胀的优劣:

1.膨胀的版本矩阵维数是一个编译期常量,编译器可以对其进行优化以提高性能。

2.非膨胀版本中的代码只有一份这样程序的时间工作区更小性能也更好。

posted @ 2020-06-11 16:45  熊鑫xxx1x  阅读(216)  评论(0)    收藏  举报