16.1模板定义
模板:函数模板和类模板;类型模板和非类型模板
template<模板形参表>
(1)inline函数模板
template<typename T>
inline T Min(T& a,T& b);
16.2定义类模板
(1)模板形参为类型形参和非类型形参两种
template<typename T,int SIZE>
class Test
{
public:
Test()
{
Init();
}
~Test()
{
;
}
void Init();
private:
T* m_pArray;
};
template<typename T,int SIZE>
void Test<T,SIZE>::Init()
{
m_pArray = new T[SIZE];
for (int nIndex = 0;nIndex<SIZE;nIndex++)
{
;
}
}
(2)模板声明
像其他任意函数或类一样,对于模板可以只声明而不定义。声明必须指明函数或类是一个模板:
template<class T>
int compare(const T&,const T&);
同一模板的声明和定义中,模板形参的名字不必相同
//all three uses of calc refer to the same function template
//forward declarations of the template
template<class T> T calc(const T&,const T&);
template<class U> T calc(const U&,const U&);
//actual definition of the template
template <class Type>
Type calc(const Type& a,const Type& b){/*...*/}
(3)typename和class区别
在函数模板形参表中,二者含义相同
nested dependent type names(嵌套依赖类型名)。
如果拿不准是否需要以typename指明一个名字是否是一个类型,那么指定是一个好主意,因为没坏处。
- template<typename T>
- void test(const T& c) {
- typename T::key_type *ptr;
- //other implementation
- }
//initialize elements of an array to zero
template <class T,size_t N > void array_init(T (&parm) [N])
{
for(size_t i = 0;i!=N;++i)
{
parm[i] = 0;
}
}
int x[42];
double y[10];
array_init(x);//instantiates array_init(int(&)[42])
array_init(y);//instantiates array_init(double(&)[10])
(5)模板代码编写原则:对实参类型的要求尽可能少
a.模板的形参是const引用:允许使用不允许复制的类型
b.函数体中的测试只用<比较:避免重载> = 等操作符
(6)编译器编译模板行为
第一阶段是编译模板定义本身时,在这个阶段中,编译器一般不能发现很多错误,可以检查到诸如漏掉分号或者变量名拼写错误之类的语法错误。
第二个错误检查时间是编译器遇见模板的使用时,在这个阶段,编译器仍没有多少检查工作可以做。对于函数模板,许多编译器只检查实参的类型和数目是否恰当。对于类模板,编译器可以检查提供的模板实参的正确数目。
产生错误的第三个时间是在实例化的时候,只有在这个时候,可以发现类型相关的错误。根据编译器管理实例化的方式,有可能在链接时报告这些错误。
16.3模板实例化
(1)
1.类模板实例化必须提供实参
Queue<string> queue;
2.函数实例化编译器自动推断:
int result = compare(10,20));
(2)模板实参推断