C++模板和STL
模板
函数模板的定义
例:
#include <iostream>
using namespace std;
//函数模板,"T"类型形参
template <typename T> //推荐使用typename
//template <class T>
T max(T x, T y){
return x<y?y:x;
}
int main(void){
int i1=100,i2=200;
// "<>"指明函数模板需要的类型实参
// "()"指明函数的调用实参
cout<<::max<int>(i1,i2)<<endl;
double d1=1.23,d2=4.56;
cout<<::max<double>(d1,d2)<<endl;
string s1="world",s2 = "hello";
cout<<::max<string>(s1,s2)<<endl;
char str1[] = "world";
char str2[] = "hello";
cout<<::max<string>(str1,str2)<<endl;
return 0;
}
函数模板的使用
模板实例化
类型参数
参考代码:
#include <iostream>
using namespace std;
template <typename T>
T add(T x,T y){
return x+y;
}
class Complex{
//复数
public:
Complex(int r,int i):m_r(r),m_i(i){
}
//cout<<c1==>operator<<(cout,c1)
friend ostream& operator<<(ostream& os,const Complex& c){
os<<c.m_r<<"+" <<c.m_i<<"i";
return os;
}
//重载+ (成员函数形式)
//c1+c2 ==>c1.operator(c2)
const Complex operator+(const Complex& c)const{
Complex res(m_r+c.m_r,m_i+c.m_i);
return res;
}
private:
int m_r;
int m_i;
};
int main(void){
cout<<add<int>(123,456)<<endl;
cout<<add<double>(1.23,4.56)<<endl;
Complex c1(1,2);
Complex c2(3,4);
cout<<c1<<","<<c2<<endl;
cout<<add<Complex>(c1,c2)<<endl; //4+6i
}
二次编译
函数模板的隐式推断
参考代码:07deduce.cpp
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename A,typename V>
void func1(A arg){
V var;
cout <<"调用参数类型:"<<typeid(arg).name()<<endl;
cout <<"局部变量类型:"<<typeid(var).name()<<endl;
}
template <typename T>
void func2(T x,T y){
cout<<"参数x类型:"<<typeid(x).name()<<endl;
cout<<"参数y类型: "<<typeid(y).name()<<endl;
}
template <typename T1,typename T2>
T1 func3(T2 x){
T1 y;
cout <<"参数x类型:"<<typeid(x).name()<<endl;
cout <<"返回y类型:"<<typeid(y).name()<<endl;
return y;
}
int main(void){
//func1(100); //error
func1<int,int>(11); //ok
//func2(100,1.23); //error
func2<int>(100,1.23); //显示推断。隐式转换
func2<double>(100,1.23);
func2(100,(int)1.23) ; //显示转换,隐式推断
func2((double)100,1.23);
//double d = func3(100); //error
double d = func3<double>(100); //显式指明返回类型,隐式推断参数类型
}
函数模板的重载
参考代码:07overload.cpp
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
void func(T x, T y){
//针对两个任意类型的数据:约束性一般
cout<<"func(1),type="<<typeid(T).name()<<endl;
}
template <typename T>
void func(T* x,T* y){
cout<<"func(2),type="<<typeid(T).name()<<endl;
}
int main(void){
int a = 10,b = 20;
func(a,b) ; //func(1) ,T = int
func(&a,&b); //func(2),T = int
func<int*>(&a,&b); //func(1) ,T= int*
return 0;
}
参考代码2: 08overload.cpp
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
void func(T x, T y){
//针对两个任意类型的数据:约束性一般
cout<<"func(1),type="<<typeid(T).name()<<endl;
}
template <typename T>
void func(T* x,T* y){
cout<<"func(2),type="<<typeid(T).name()<<endl;
}
void func(const char* x,const char* y){
//针对性两个const char *:约束性更强
cout<<"func(3),type="<<typeid(x).name()<<endl;
}
int main(void){
int a = 10,b = 20;
func(a,b) ; //func(1) ,T = int
func(&a,&b); //func(2),T = int
func<int*>(&a,&b); //func(1) ,T= int*
const char* s1 = "123";
const char* s2 = "456";
func(s1,s2); //func(3);
func<>(s1,s2); //func(2)
//如果匹配func(2),类型实参const char*,调用参数类型应该式const char**,无法和调用实参s1,s2
//相匹配,所以只能选中第一个版本
func<const char*>(s1,s2); //func(1)
return 0;
}
类模板的定义
类模板的使用
类模板的实例化
类模板中的成员函数
参考代码:09ct.cpp
#include <iostream>
using namespace std;
template <typename T>
class Compare{
//类模板
public:
Compare(T x,T y):m_x(x),m_y(y){
}
T max(void) const{
return m_x < m_y ? m_y:m_x;
}
T min(void) const {
//return m_x >m_y ?m_y:m_x;
//对于类模板的设计者,应该尽可能减少对类型实参的要求,方便类模板的使用者
return m_x < m_y ? m_x:m_y;
}
private:
T m_x;
T m_y;
};
class Integer{
public:
Integer(int data):m_data(data){
}
friend ostream& operator<<(ostream& os,const Integer& i){
os<<i.m_data;
return os;
}
//重载《成员函数形式》
bool operator<(const Integer& i) const{
return m_data<i.m_data;
}
//重载>(成员函数形式)
bool operator >(const Integer& i) const{
return m_data>i.m_data;
}
private:
int m_data;
};
int main(void){
//先结合<int>实例化具体的类,再使用该类实例化ci对象
//Compare<int> ci(123,456);
//cout<<"max="<<ci.max()<<",min="<<ci.min()<<endl;
//Compare<double> cd(1.23,4.56);
//cout<<"max="<<cd.max()<<",min="<<cd.min()<<endl;
//cout<<sizeof(Compare)<<endl; //error
//cout<<sizeof(Compare<int>)<<endl; //ok ,8
//Compare cc('A','B'); //error
//Compare<int>ci(123,456);
//cout<<"max="<<ci.max()<<",min="<<ci.min()<<endl;
Integer i1(123);
Integer i2(456);
Compare<Integer>cInt(i1,i2);//ok
cout<<"max="<<cInt.max()<<endl;
return 0;
}
类模板的静态成员
参考代码:static.cpp
#include <iostream>
using namespace std;
template <typename T>
class A{
public:
void printAddr(void){
cout<<"&m_data:"<<&m_data<<",s_data="<<&s_data<<endl;
}
private:
int m_data; //普通成员变量
static int s_data; //静态成员便利
};
template <typename T>
int A<T>::s_data; //定义
int main(void){
A<int> i1,i2;
A<double> d1,d2;
//一共有几个m_data(4)个?s_data?(2个
i1.printAddr();
i2.printAddr();
d1.printAddr();
d2.printAddr();
}
类模板的递归实例化
参考代码:
#include <iostream>
using namespace std;
template <typename T>
class Array{
public:
//下标操作符重载
T& operator[](size_t i){
return m_a[i] ;
}
const T& operator[] (size_t i)const{
return m_a[i] ;
}
//获取容器中元素个数
size_t size(void)const{
return sizeof(m_a)/sizeof(m_a[0]);
}
//重载<<
friend ostream& operator<<(ostream& os,const Array& arr){
for(size_t i=0;i<arr.size();i++) {
os<<arr[i] <<' ';
}
return os;
}
private:
T m_a[3];
};
int main(void){
Array<int>a1;
a1[0] = 10;
a1[1] = 20;
a1[2] = 30;
cout<<a1<<endl;
Array<int>a2;
a2 = a1;
cout<<a2<<endl;
//递归实例化:用类模板实例化的类型,作为类型实参,再实例化该类模板自身
Array<Array<int> >aa;//二维数组
for(size_t i=0;i<aa.size();i++)
for(size_t j=0;j<aa[i].size();j++)
aa[i][j] = i*3+j+1; //1 2 3 4 5 6 7 8 9
for(size_t i=0;i<aa.size();i++){
cout<<aa[i] <<endl;
}
return 0;
}
类模板的特化
全类特化
参考代码:
#include <iostream>
#include <cstring>
using namespace std;
template <typename T>
class Compare{
public:
Compare(T x,T y):m_x(x),m_y(y){
}
T Max(void){
cout<<"通用版本" <<endl;
return m_x<m_y?m_y:m_x;
}
private:
T m_x;
T m_y;
};
template <>
class Compare<char *>{
//全类特化(针对char *实例化的具体类)
public:
Compare(char *x,char *y):m_x(x),m_y(y){
}
char *Max(void){
cout<<"特化版本"<<endl;
return strcmp(m_x,m_y)<0?m_y:m_x;
}
private:
char *m_x;
char* m_y;
};
int main(void){
Compare<int> cInt(123,456);
cout<<cInt.Max()<<endl; //456
char s1[] = "world";
char s2[] = "hello";
Compare<char *>cChar(s1,s2);
cout<<cChar.Max()<<endl; //world
return 0;
}
成员特化
参考代码:
#include <iostream>
#include <cstring>
using namespace std;
template <typename T>
class Compare{
public:
Compare (T x,T y):m_x(x),m_y(y){
}
T Max(void)const{
cout<<"通用版本" <<endl;
return m_x<m_y?m_y:m_x;
}
private:
T m_x;
T m_y;
};
template<>
char *Compare<char *>::Max(void)const{
//成员特化(针对char* 重写的Max函数)
cout<<"特化版本"<<endl;
return strcmp(m_x,m_y)<0?m_y:m_x;
}
int main(void){
Compare<int> cInt(123,456);
cout<<cInt.Max()<<endl; //456
char s1[] = "world";
char s2[] = "hello";
Compare<char *>cChar(s1,s2);
cout<<cChar.Max()<<endl; //world
return 0;
}
局部(偏)特化
模板的使用技巧
类模板参数的缺省值
参考代码:
#include <iostream>
#include <typeinfo>
using namespace std;
template<typename A=double,typename B=A>
class X{
public:
static void foo(void){
cout<<typeid(A).name()<<","<<typeid(B).name()<<endl;
}
};
template<typename A=int,typename B=double>
void fun(void){
cout<<typeid(A).name()<<","<<typeid(B).name()<<endl;
}
int main(void){
X<int,int>::foo();
X<int>::foo();
X<double>::foo();
X<>::foo();
return 0;
}
数值型模板参数(非类型参数)
参考代码
#include <iostream>
using namespace std;
template<typename T,size_t S=10/*数值型模板参数*/>
class Array{
public:
T& operator[](size_t i){
return m_arr[i] ;
}
const T& operator[](size_t i)const{
return m_arr[i] ;
return const_cast<Array&>(* this) [i];
}
size_t size(void) const{
return sizeof(m_arr)/sizeof(m_arr[0] );
}
friend ostream& operator<<(ostream& os,const Array& arr){
for(size_t i=0;i<arr