目录
一、非类型模板参数
1、非类型模板参数的介绍
模板参数分为类类型模板参数和非类型模板参数。
- 类类型模板参数:出现在模板参数中,跟在class或者typename后面的参数类型名称。
- 非类型模板参数:用一个常量作为类或者函数模板的一个参数,在模板中可以将该参数当成常量来使用。
注意:浮点数、类对象、字符串不可以做非类型模板参数;非类型的模板参数必须在编译期就能确认结果。
2、非类型模板参数的使用
类型模板参数在实例化时需要指定类型,非类型模板参数可以在实例化时指定值也可以给定缺省值。
-
template<size_t m,size_t n =
10>
-
void test()
-
{
-
std::cout << m <<
" " << n<<std::endl;
//2 10
-
}
-
-
int main()
-
{
-
test<
2>();
-
return
0;
-
}
二、模板的特化
1、模板特化的概念
使用模板可以编写与类型无关的代码,但是在一些特殊的情况下使用模板可能会得到错误的结果,为了解决这些错误的结果就需要对模板进行特化。即,在原模板的基础上对特殊的类型进行特殊化的处理。模板的特化分为函数模板特化和类模板特化。
2、函数模板的特化
函数模板特化的步骤
- 必须有一个基础的函数模板
- 关键字template后面跟一对<>
- 函数名后面跟一对<>,里边指定需要特化的类型
- 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误
-
template<class T>
-
bool
IsEqual
(T& left,T& right)
-
{
-
return left == right;
-
}
-
-
//函数模板的特化
-
template<>
-
bool IsEqual<
char*>(
char*& left,
char*& right)
-
{
-
if(
strcmp(left, right) >
0)
-
return
true;
-
return
false;
-
}
注意:一般情况下,函数模板遇到不能处理或者处理有误的类型时都是直接给出该类型的函数
3、类模板的特化
1)全特化
全特化顾名思义就是将类模板的模板参数列表中全部进行特化。
-
template<
class T1, class T2>
-
class
Data
-
{
-
public:
-
Data()
-
{
-
cout<<
"Data<T1, T2>" <<
endl;
-
}
-
private:
-
T1 _d1;
-
T2 _d2;
-
};
-
-
//对日期雷模板的类模板参数全部进行特化
-
template<>
-
class Data<int, char>
-
{
-
public:
-
Data()
-
{
-
cout<<
"Data<int, char>" <<
endl;
-
}
-
private:
-
int _d1;
-
char _d2;
-
};
-
void TestVector()
-
{
-
Data<
int,
int> d1;
-
Data<
int,
char> d2;
-
}
2)偏特化
偏特化的两种表现形式
- 对类模板的模板参数列表中的一部分进行特化
-
// 将第二个参数特化为int
-
template <
class T1>
-
class Data<T1, int>
-
{
-
public:
-
Data() {
cout<<
"Data<T1, int>" <<
endl;}
-
private:
-
T1 _d1;
-
int _d2;
-
};
- 对类模板的模板参数列表中的类型特华为指针或引用
-
//两个参数偏特化为指针类型
-
template <typename T1, typename T2>
-
class
Data <
T1*,
T2*>
-
{
-
public:
-
Data() {cout<<
"Data<T1*, T2*>" <<endl;}
-
private:
-
T1 _d1;
-
T2 _d2;
-
};
-
//两个参数偏特化为引用类型
-
template <typename T1, typename T2>
-
class
Data <
T1&,
T2&>
-
{
-
public:
-
Data(
const T1& d1,
const T2& d2)
-
: _d1(d1)
-
, _d2(d2)
-
-
{
-
cout<<
"Data<T1&, T2&>" <<endl;
-
}
-
private:
-
const T1& _d1;
-
const T2& _d2;
-
};
-
void test2 ()
-
{
-
Data<
double,
int> d1;
// 调用特化的int版本
-
Data<
int,
double> d2;
// 调用基础的模板
-
Data<
int *,
int*> d3;
// 调用特化的指针版本
-
Data<
int&,
int&> d4(
1,
2);
// 调用特化的指针版本
-
}
三、模板的分离编译
1、什么是分离编译
一个项目由多个源文件组成,每个源文件单独编形成目标文件,通过链接将所有目标文件链接在一起形成可执行文件,就称为分离编译。
2、模板的分离编译
加入模板的声明在头文件中,定义在源文件(.cc文件)中,则对模板进行编译:
解决方法:模板的声明和定义放在一起(同一个.hpp文件中),这样在预处理阶段,编译器会将头文件展开在其他源文件中。
四、模板的优点和缺点
优点
- 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
- 增强了代码的灵活性
缺点
- 模板会导致代码膨胀问题,也会导致编译时间变长
- 出现模板编译错误时,错误信息非常凌乱,不易定位错误
转载:https://blog.csdn.net/qq_47406941/article/details/116103464
查看评论