C++语法学习笔记六十:模板全特化、偏特化(局部特化)

实例代码:

// 

#include <iostream>
#include <vector>

using namespace std;

template<typename T, typename U>
struct TC{  //泛化的TC类模板
	TC(){
		cout << "泛化版本构造函数" << endl;
	}

	void functest(){
		cout << "泛化版本" << endl;
	}
};

//当T和U 这两个类型模板参数都为int类型时,我们希望做一个特化版本
//全特化:就是所有类型模板参数(这里T和U),都得用具体的类型代表。
template<> //全特化:所有类型模板参数都用具体类型代表,所以这里的template后边的<>里就为空
struct TC<int, int> //上边的T绑定到这里的第一个int, 上边的U绑定到这里的第二个int
{
	TC(){
		cout << "int , int 特化版本构造函数" << endl;
	}

	//在这里可以对该特化版本做单独处理
	void functest(){
		cout << "int, int 的特化版本" << endl;
	}
};



template<> //全特化:所有类型模板参数都用具体类型代表,所以这里的template后边的<>里就为空
struct TC<double, int>
{
	//在这里可以对该特化版本做单独处理
	void functest(){
		cout << "double, int 的特化版本" << endl;
	}
};

template<> //全特化
void TC<double, double>::functest()
{
	cout << "double, double 的functest()特化版本" << endl;
};


//泛化版本
template <typename T, typename U, typename W> //带三个类型模板参数
struct TC1
{
	void functest(){
		cout << "泛化版本" << endl;
	}
};

//从参数数量上进行偏特化,我们现在绑2个类型模板参数。留一个类型模板参数。
template<typename U> //因为另外两个被我绑定到具体类型,所以这里只剩下一个U类型模板参数了。
struct TC1<int, U, double> //大家注意, 这里可以跳着来。
{
	void functest(){
		cout << "偏特化 int, U, double 版本" << endl;
	}
};


//泛化版本
template<typename T>
struct TC2{
	void functest(){
		cout << "泛化版本" << endl;
	}
};

//模板参数范围上的特化版本
template<typename T>
struct TC2<const T>{ //const 的特化版本
	void functest(){
		cout << "const T特化版本" << endl;
	}
};

template<typename T>
struct TC2<T*>{ //T* 的特化版本 告诉编译器,如果使用指针,就调用这个版本
	void functest(){
		cout << "T*特化版本" << endl;
	}
};

template<typename T>
struct TC2<T&>{ //左值引用特化版本
	void functest(){
		cout << "T&左值引用特化版本" << endl;
	}
};

template<typename T>
struct TC2<T&&>{ //右值引用特化版本
	void functest(){
		cout << "T&&右值引用特化版本" << endl;
	}
};

template <typename T, typename U>
void tfunc(T &tmprv, U& tmprv2)
{
	cout << "tfunc泛化版本" << endl;
	cout << tmprv << endl;
	cout << tmprv2 << endl;
}

//全特化版本, T = int, U = double 
template <>
void tfunc(int &tmprv, double& tmprv2)
{
	cout << "-------begin--------" << endl;
	cout << "tfunc特化int,double" << endl;
	cout << tmprv << endl;
	cout << tmprv2 << endl;
	cout << "----------end---------" << endl;
}

//重载函数
void tfunc(int &tmprv, double& tmprv2)
{
	cout << "tfunc重载函数(int, double)" << endl;
}

//函数模板偏特化
//template<typename U>
//void tfunc<double, U>(double & tmprv, U& tmprv2) //"tfunc": 非法使用显式模板参数
//{
	//..
//}


int main()
{
	//特化: 相反   泛化:模板,可以随便指定类型。
	//特化:对特殊的类型(类型模板参数)进行特殊的对待,给它开小灶,给它写适合它的专用代码。

	//一:类模板特化
	//(1.1) 类模板全特化
	//(a) 常规全特化
		//必须先有泛化版本才能存在特化版本,只要涉及特化,一定先存在泛化:
	//特化版本代码编译器会优先选择。
	TC<char, int> tchar;
	tchar.functest(); //泛化版本

	TC<int, int> tcint;
	tcint.functest(); //int, int 的特化版本

	TC<double, int> tdint;
	tdint.functest(); //double, int 的特化版本
	//这种特化版本可以任意多,咱们目前是写了两个

	//(b) 特化成员函数而不是模板
	TC<double, double> tdbldbl;  //泛化版本对象,调用的是泛化版本的构造函数。
	tdbldbl.functest(); //因为我们特化了double,double 类型的functest函数,所以这里调用 的是特化的functest()函数。

	//(1.2) 类模板偏特化 (局部特化)
	//偏特化从两方面说起:一个是从模板参数数量上, 一个是从模板参数范围上
	//(a) 模板参数数量
	TC1<double, int, double> tcdi;
	tcdi.functest(); //泛化版本

	TC1<int, int, double> teii;
	teii.functest(); //偏特化int, U, double 版本

	//(b) 模板参数范围上:int const int (比int小),
				//原来T, 现在 T* (从任意类型T缩小为指针类型T*)
				//原来是T,现在T& 左值引用,或者现在是T&& (右值引用),都叫返回缩小。

	TC2<double> td;
	td.functest(); // 泛化版本

	TC2<double*> tpd;
	tpd.functest(); // T* 特化版本

	TC2<const double*> tpd2;
	tpd2.functest(); // T* 特化版本

	TC2<const double> td3;
	td3.functest(); // const T 特化版本

	TC2<int&> tcyi;
	tcyi.functest(); //T& 左值引用特化版本

	TC2<int&&> tcyii;
	tcyii.functest(); //T&& 右值引用特化版本

	//局部特化 , 特化完了之后它本质还是个模板。全特化,特化完了等于一个具体的类了。

	//二: 函数模板特化
	//(2.1) 函数模板全特化
	const char *p = "I Love China!";
	int i = 12;
	tfunc(p, i); //T = const char *, tmprv = const char *& , U = int, tmprv2 = int&


	double db = 15.8f;
	tfunc(i, db);

	//全特化函数模板实际上等价于实例化  一个函数模板 ,并不是等价于一个函数重载。
	//void tfunc<int, double>(int&, double &){}; 全特化, 等价于实例化一个函数模板
	//void tfunc(int &tmprv, double& tmprv2) //重载函数应该长这样

	//编译器选择最最合适:普通优先,特化版本,泛化版本;

	//如果你传递个字符串给函数模板
	//函数模板的特化版本中,如果有数组类型模板参数,指针类型模板参数。
	//编译器会认为  数组类型模板参数 比指针类型模板参数更合适。所以编译器会为你选择数组类型的模板参数的特化版本。

	//(2.2) 函数模板偏特化
	//函数模板不能偏特化

	//三: 模板特化版本 放置位置建议
	//模板定义、实现都放在一个 .h文件中;
	//模板的特化版本和模板的泛化版本都应该放在同一个.h文件中。
	//.h 文件中前边放泛化版本,后边放特化版本。



	system("pause");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值