文章目录
- 一、typename的使用
- 二、非类型模板参数
- 三、模板的特化
- 1.概念
- 2.函数的模板特化
- 3.类的模板特化
- ① 全特化
- ② 偏特化
一、typename的使用
前面我们在使用模板参数的时候可以使用class,也可以使用typename定义模板参数,现在typename有了新的作用
template<class container>
void Print(const container& v)
{
//编译器不确定Container::const_iterator是类型还是对象
//没有实例化的类模板,需要使用typename明确告诉编译器container是一个类型,否则编译器报错
typename container::const_iterator it = v.begin();
//也可使用auto auto it=v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
二、非类型模板参数
模板参数分类类型形参与非类型形参。
类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
实例:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<list>
#include<array>
using namespace std;
//静态栈
//非类型模板参数
//1.常量
//2.必须是整形,不可在类中修改
template<class T,size_t N=10>
class Stack
{
public:
void func()
{
//常量,不可修改
//N = 10;
}
private:
T _a[N];
int _top;
};
int main()
{
Stack<int, 10> st1;
Stack<int, 100> st2;
//st1.func();
//非类型模板参数使用 定长数组 C++11
//array只有一个优势,越界检查严格
array<int,10> a;
for (auto e : a)
{
cout << e << " ";
}
cout << endl;
return 0;
}
使用非类型模板参数实现了一个新的容器,array - 定长数组
三、模板的特化
1.概念
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板
namespace tzc
{
template<class T>
bool less(T a, T b)
{
return a < b;
}
}
int main()
{
int a = 10;
int b = 20;
int* c = &a;
int* d = &b;
cout << tzc::less(a, b) << endl;
cout << tzc::less(c, d) << endl; // 传入指针 ,只会比较指针
return 0;
}
我们实现了一个函数模板用来比较两个变量的大小,但是比较的类型有限,如果传入指针类型的变量,比较大小的结果往往不是我们所想要的,此时我们需要实现一个函数模板的特化用来处理特殊情况
2.函数的模板特化
函数模板的特化步骤:
1.必须要先有一个基础的函数模板
2.关键字template后面接一对空的尖括号<>
3.函数名后跟一对尖括号,尖括号中指定需要特化的类型
4.函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
//函数模板
template<class T>
bool Less(T left, T right)
{
return left < right;
}
//函数模板的特化 也可重载
//这种只能解决int类型的问题
template<>
bool Less<int*>(int* left, int* right)
{
return *left < *right;
}
//解决各种指针类型的比较,
template<class T>
bool Less(T* left, T* right)
{
return *left < *right;
}
int main()
{
cout << Less(1, 2) << endl;
int a = 1, b = 2;
cout << Less(&a, &b) << endl;
return 0;
}
3.类的模板特化
① 全特化
//类模板
template<class T1,class T2>
class Date
{
public:
Date() { cout << "Date<T1 ,T2>" << endl; }
private:
T1 _d1;
T2 _d2;
};
//全特化
template<>
class Date<int ,double>
{
public:
Date() { cout << "Date<int,double>" << endl; }
};
int main()
{
Date<int, int> d1;
Date<int, double>d2;
return 0;
}
② 偏特化
//类模板
template<class T1,class T2>
class Date
{
public:
Date() { cout << "Date<T1 ,T2>" << endl; }
private:
T1 _d1;
T2 _d2;
};
//偏特化,特化部分参数
template<class T>
class Date<T,double>
{
public:
Date() { cout << "Date<T,double>" << endl; }
};
//偏特化,对某些类型进行进一步特化
template<class T1,class T2>
class Date<T1*,T2*>
{
public:
Date() { cout << "Date<T*,T*>" << endl; }
};
int main()
{
Date<double, double>d3;
Date<int*, int*>d4;
Date<double*, double*>d5;
return 0;
}