模板作为C++泛型编程的基础十分重要,其使得一份代码能用于处理多种数据类型。而有些时候,我们会希望对一些特定的数据类型执行不同的代码,这时就需要使用模板特例化(template specialization)。
函数模板特例化
首先说一个重要的,函数模板的特例化并不是函数重载,每一个特例化实际上是提供了另一个模板定义式,因此特例化不影响函数匹配。

特例化一个函数模板时,必须为模板中的每个参数都给出实参,关键字template后跟一个<>

类模板特例化
类模板中,提供所有实参时叫做全特化,类模板的全特化和函数模板的特例化上没有什么不同(除了一个是类模板一个是函数模板:D)

与函数模板必须为每个模板参数提供实参不同,类模板支持部分特例化,也叫偏特化(partial specialization)
当定义类模板的偏特化版本时,模板参数只需包含原模板中那些还未确定类型的模板参数,在类名之后需要添加<>,且需要按对应位置填入实参。

template<typename T, typename P>
class test {
public:
	test() { cout << "这是未特化的类模板\n"; }
};

template<typename P>//T被特化为bool类型,template<>中无需typename T
class test<bool,P> {
public:
	test() { cout << "这是bool偏特化的类模板\n"; }
};

template<>//全特化,template<>可以为空
class test<int*, int*> {
public:
	test(){ cout << "这是接受两个指针类型的全特化的类模板\n"; }
};

{
	test<int*, int> t1;//会调用未特化的类模板
	test<bool,int> t2;//会调用bool偏特化
	test<int*, int*> t3;//全特化版本
}
#include <iostream>

using namespace std;


template<typename T>
class MyVector {

public:
	MyVector<T>() { cout << "MyVector<T>()" << endl; }

};

//针对 char * 模板特例化
template<> 
class MyVector<char *> {

public:
	MyVector() { cout << "MyVector<char *>" << endl; }

};

//模板特例化,只针对指针类型提供的部分特例化,只知道指针,但是什么指针不知道
template<typename Ty>
class MyVector<Ty*> {

public:
	MyVector() { cout << "MyVector<Ty *>" << endl; }

};

//template<>
//class MyVector<int(*)(int, int)> {
//public:
//	MyVector() { cout << "int (*)(int,int )" << endl; }
//
//};

//template<typename T>
//class MyVector<T(*)(T, T)> {
//public:
//	MyVector() { cout << "MyVector<T(*)(T, T)>" << endl; }
//
//};
//
//template<typename R1, typename R2, typename R3>
//class MyVector<R1(*)(R2, R3)> {
//	public:
//		MyVector() { cout << "MyVector<R1(*)(R2, R3)>" << endl; }
//
//};


//template<typename R1, typename R2, typename R3>
//class MyVector<R1(R2, R3)> {
//	public:
//		MyVector() { cout << "MyVector<R1(R2, R3)>" << endl; }
//
//};

int sum(int x, int y) {
	return x + y;
}

int main() {

	MyVector<int> v1; //缺省模板

	MyVector<char *> v2;// char * 特例化模板

	MyVector<int *> v3;// 使用部分特例化 class MyVector<Ty*>



	MyVector<int (*)(int,int)> v4; // 使用部分特例化 class MyVector<Ty*> ,int (*)(int,int) 指向函数的指针

    // 如何针对 MyVector<int (*)(int,int)> v4;写一个完全特例化版本? 写法如下
	/* 
		template<>
		class MyVector<int(*)(int, int)> {
		public:
			MyVector() { cout << "int (*)(int,int )" << endl; }

		};
	*/

	// 如何针对 MyVector<int (*)(int,int)> v4;写一个部分特例化版本? 写法如下 两种
	
	/*  写法1
	    MyVector 元素是函数指针,返回类型是R1,两个参数类型分别是R2,R3  提供部分特例化
		template<typename T>
		class MyVector<T(*)(T, T)> {
		public:
			MyVector() { cout << "MyVector<T(*)(T, T)>" << endl; }

		};
	*/

	/*
		写法2
		MyVector 元素是函数指针,返回类型是R1,两个参数类型分别是R2,R3 提供部分特例化 
		template<typename R1, typename R2, typename R3>
		class MyVector< R1(*)(R2, R3) > 
		{
		public:
			MyVector() { cout << "MyVector<R1(*)(R2, R3)>" << endl; }

		};
	*/



	MyVector<int(int, int)> v5; //元素是函数对象类型,使用默认的函数版本,也可以使用如下方式

	/* 
	template<typename R1, typename R2, typename R3>
	class MyVector<R1(R2, R3)>//针对函数类型,进行部分特例化,有一个返回值,有两个形参
	{
	public:
		MyVector() { cout << "MyVector<R1(R2, R3)>" << endl; }

	};
	*/



	//函数指针类型
	typedef int (*PFUNCTION) (int, int);
	PFUNCTION pf1 = sum;
	pf1(12, 13);

	//函数类型
	typedef int PFUNCTION2 (int, int);
	PFUNCTION2 * pf2 = &sum;
	(*pf2)(12, 13);


	system("pause");
	//有完全特例化能匹配就用完全特例化版本,有部分特例化版本就用部分特例化,再没有就用缺省模板
	return 0;
}

//问题:这种写法可以,但是  typename T 这种方式  范围太大了!!优化如下
template<typename T>
void function(T _t) {
	cout << typeid(T).name() << endl;
}


template<typename R, typename R1, typename R2>
//细分到可以取出返回值类型R1,形参1类型R2,形参2类型R3  还可以继续细分 如下
void function(R1(*)(R2,R3)) {

	cout << typeid(R1).name() << endl; 
	cout << typeid(R2).name() << endl;
	cout << typeid(R3).name() << endl;

}

//效果,继续细分到可以取出返回值类型R1,哪个类类型T,形参1类型R1,形参2类型R2  Good
template<typename R, typename T, typename R1, typename R2>

void function3(R1(T::*)(R2, R3)) {

	cout << typeid(T).name() << endl;
	cout << typeid(R1).name() << endl;
	cout << typeid(R2).name() << endl;
	cout << typeid(R3).name() << endl;

}


class Test {


public:
	int sum(int x, int y) { return x + y; }

};

int main() {

	function3(&Test::sum);
}