跳至主要內容

模板的完全特例化和非完全特例化

张威大约 3 分钟c/c++类模板

模板的完全特例化和非完全特例化

有完全特例化,就选择对应的,有部分特例化,就匹配,没有的话,就

template<typename T>
bool compare(T a, T b) {
    cout << "template compare" << endl;
    return a > b;
}

int main() {
    compare(10, 20);
    compare("aaa", "bbb"); //T const char*
	return 0;
}

能运用在int类型上,字符串比较就不行了。 此时的实例化compare代码就不行了,

需要多加一个模板的完全特例化:完全特例化: 类型完全是已知的)

模板的完全特化

template后面的<>什么参数都没有,表示参数都是已知的。

template<>
bool compare<const char*>(const char* a, const char* b) {
	cout << "compare<const char*>" << endl;
    return strcmp(a, b) > 0;
}

模板的部分特例化

#include <iostream>
#include <cstdio>
using namespace std;

template<typename T>
class Vector
{
public:
	Vector() { cout << "call Vector template init" << endl; }
};

//下面这个是对char*类型提供的完全特例化版本  #1
template<>//特例化的语法
class Vector<char*>
{
public:
	Vector() { cout << "call Vector<char*> init" << endl; }
};

//下面这个是对指针类a型提供的部分特例化版本  #2
template<typename Ty>
class Vector<Ty*>
{
public:
	Vector() { cout << "call Vector<Ty*> init" << endl; }
};

//指针函数指针(有返回值,有两个形参变量)提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(*)(A1, A2)>
{
public:
	Vector() { cout << "call Vector<R(*)(A1, A2)> init" << endl; }
};

//针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(A1, A2)>
{
public:
	Vector() { cout << "call Vector<R(A1, A2)> init" << endl; }
};

int sum(int a, int b) { return a + b; }

int main()
{
	Vector<int> vec1;
	Vector<char*> vec2;
	Vector<int*> vec3;
	Vector<int(*)(int, int)> vec4;
	Vector<int(int, int)> vec5;//function

	//注意区分一下函数类型和函数指针类型
	//用函数指针定义的变量本身就是一个指针
	typedef int(*PFUNC1)(int, int);		//PFUNC1是函数指针类型
	PFUNC1 pfunc1 = sum;
	cout << pfunc1(10, 20) << endl;

	typedef int PFUNC2(int, int);		//PFUNC2是函数类型
	//函数类型在定义的时候,需要将指针*加上
	PFUNC2* pfunc2 = sum;
	cout << (*pfunc2)(10, 20) << endl;

	return 0;
}

模板的实参推演

//T包含了所有的大的类型 返回值,所有形参的类型都取出来
tempalte<typename T>
void func(T a) {
	cout << typeid(T).name() << endl;
}

int sum(int a, int b) { return a + b;}

int main() {
    func(10);	//int
    func("aaa");	//const char *
	func(sum);	//T int (*)(int, int) 	int (int, int)
}

我们我们直接用一个函数指针的模板部分特例化来做:

template<typename R, typename A1, typename A2> 
void fun2(R(*a)(A1, A2)) {
	cout << typeid(R).name() << endl;	//int
	cout << typeid(A1).name() << endl;	//int
	cout << typeid(A2).name() << endl;	//int
}

fun2(sum);	

定义一个Test类,里面有一个成员函数sum

class Test {
public:
	int sum(int a, int b) { return a + b; }
};

template <typename T>
void func(T a) {
    cout << typeid(T).name << endl;
}

int main() {
    func(&Test::sum); //int (__thiscall Test::*)(int, int)
}

得到一个指向成员方法的函数指针类型。将其参数细分:

template<typename R, typename T, typename A1, typename A2>
void func3(R(T::* a)(A1, A2)) {
    cout <<typeid(R).name() <<endl;	//int
    cout <<typeid(T).name() <<endl;	//class Test
    cout <<typeid(A1).name() <<endl;	//int
    cout <<typeid(A2).name() <<endl;	//int
}

总结

这几个例子指导我们在写函数模板,类模板时,针对一个具体情况,把他们一个大类型的细分类型,定义相应的参数,接收大类型的所有细分类型,使用的就是模板部分偏特化