- Rule44: 将与参数无关的代码抽离templates
Factor parameter-independent code out of templates
使用Templates可能会导致代码膨胀,其二进制码带着重复或几乎重复的代码,数据或两者。其结果有可能源码看起来合身而整齐,但目标码却不是那么回事。所以需要知道如何避免这样的二进制浮夸。编写templates时,同样是将重复部分抽出来,但其中有个窍门。在非模板代码中,重复十分明确:你能够看到两个函数或两个classes之间的重复。然而在templates代码中,重复是隐晦的:毕竟只存在一份templates源码,所以你必须训练自己去感受当templates被具现化多次时可能发生的重复。
如如下代码:
template<typename T,std::size_t n>
class SquareMatrix{
public:
void invert();
};
//考虑如下代码:
SquareMatrix<double,5> sm1;
sm1.invert();
SquareMatrix<double,10> sm2;
sm2.invert();
这会具现化两份invert。这些函数并非完全相同,因为其中一个操作的是5*5矩阵,而另一个是10*10矩阵(n就是非类型模板参数)。但除了常量5和10,两个函数的其他部分完全相同。这是template引出代码膨胀的一个典型例子。
非类型模板参数(non-type template parameters)造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数。
- Rule45: 运用成员函数模板进行隐式模板类型转换
指针支持隐式转换(implicit conversion), 在动态绑定中,派生类指针可以转换为基类指针.
但是模板的实例化(instantiations)之间, 是单独存在的,没有明确的直接转换关系
派生类的实例化的模板(SmartPtr), 不能转换为基类实例化的模板(SmartPtr);
为了使用转换只能发生在可以转换的指针, 如”Derived->Base”, 不能逆序, 所以引入相关约束判断是否可以转换.
在成员初始化列表(member initialization list)中调用get()函数, 判断是否可以隐式转换.
使用成员函数模板的构造函数, 是成员函数的一种, 并不是重载复制构造函数, 所以类会自动生成一个默认构造函数.
#include <iostream>
using namespace std;
template<typename T>
class SmartPtr{
public:
SmartPtr(){}//默认构造函数
template<typename U>
SmartPtr(const SmartPtr<U> & other)
{
heldPtr = other.get();
cout<<"SmartPtr::CopyConstructor"<<endl;
}
T* get() const
{
return heldPtr;
}
private:
T * heldPtr;
};
class Base{};
class Derived:public Base{};
int _tmain(int argc, _TCHAR* argv[])
{
SmartPtr<Derived> spd;
SmartPtr<Base> spb(spd);
//SmartPtr<Base> spb1;
//SmartPtr<Derived> spd1(spb1); //无法进行隐身转换
SmartPtr<Base> spd2;
SmartPtr<Base> spd21(spd2); //使用默认的复制构造函数
getchar();
return 0;
}
当出现 逆转换时,直接在编译阶段会报错。
注意:原始 成员函数模板的写法如下:
template<typename T>
class SmartPtr{
public:
template<typename U>
SmartPtr(const SmartPtr<U> &other);
}
以上代码的意思是: 对任何类型T和任何类型U,这里可以根据SmartPtr< U>生成一个SmartPtr< T>。因为 SmartPtr< T>有个构造函数接受一个SmartPtr< U>参数。但是这种simple model存在的问题就是没有约束性,可以正反进行转换,必须从某方面对这一member template所创建的成员函数群进行拣选或筛选。于是出现了上面的代码。再说一次,因为是编译时会具化代码,如果转换不符合关系,会直接报错。
还需要注意:成员函数模板与默认的构造函数不冲突,如果没有指明构造函数,会给出提示需要进行声明。