目录
一、非类型模板参数:
1.1定义:
- 在C++中,除了普通的类型参数外,模板还可以接受非类型参数(Non-type Parameter)。非类型参数是指模板参数中的一个特殊种类,它不是类型,而是一个常量表达式,可以是整数、枚举、指针等。
1.2用途:
- 数组大小:可以在编译时确定数组的大小。
- 枚举值:可以在编译时确定枚举的值。
- 容器容量:可以在编译时确定容器的容量。
- 模板元编程:用于实现模板元编程技术,例如计算阶乘、斐波那契数列等。
1.3举例:
- 如果要初始化一个1000大小和10大小的栈。
template <typename T, int Size> class Stack { ... } Stack<int,1000> s1; Stack<int,10> s2;
二、模板特化:
2.1概念:
- 模板特化(Template specialization)是C++中模板的一种特性,它允许为模板参数的特定值或特定类型提供定制化的实现。
- 全特化(Full specialization):为模板的所有参数提供特定的实现。
- 偏特化(Partial specialization):只为模板的一部分参数提供特定的实现。
2.2实例解析——全特化:
- 有一个类有两个模板参数T1和T2。
template<class T1,class T2> class test { public: test() { cout<<"test"<<endl; } private: T1 _n1; T2 _n2; }
- 如果要特殊处理T1为int,T2为double的情况,就可以将模板特化为:
template<> class test<int,double> { ... }
- 需要注意的是一定要在开头写template<>
2.3实例解析——偏特化:
- 一部分模板参数被特化。
template<class T1> class test<T1,double> { ... }
- 先匹配全特化,如果没有再匹配偏特化,最后才匹配无特化的模板。
2.4对某种类型特化:
- 处理模板实参为指针的情况。
template<class T1,class T2> class test<T1*,T2*> { ... }
- 如果传来实例化的实参为指针类型,就走这个特化。
三、模板的分离编译:
3.1模板分离编译会造成的问题:
- 在C++中,模板实例化的过程主要发生在编译阶段,而不是链接阶段。当链接时,由于没有实例化模板为具体的类,就不会在符号表生成对应的符号。
- 链接器在链接阶段会找不到相应的符号,导致未定义符号错误。
3.2解决分离编译问题——显式实例化:
- 在源文件中明确地实例化可能需要的模板类型。
- 比如对函数模板ADD,分别显式实例化他的int和double版本。
- 实例化不够灵活,需要手动实例化可能的类型。
- 可能导致代码膨胀,多个源文件可能在不知情的情况下,对一个类型实例化多份模板。
实例化一份int template int ADD<int> (const int& left,const int& right) 实例化一份double template double ADD<int> (const double& left,const double& right)
3.3将模板声明和定义分离,但是都写在一个头文件中。
- 最常见且直接的方法是将模板的声明和定义都放在头文件中。这确保了每个使用模板的翻译单元都能看到完整的模板定义,并能够生成所需的实例化代码。