【模板实例化和特例化】

隐式实例化

当我们写好了一个函数模板,但实际上它只是一个编译指令,只有当我们用的时候,才会根据函数模板去生成具体的函数,而什么时候用取决于使用者。这也就是隐式实例化。

template<typename T>
T add(T a, T b)
{
	return a+b;
}

int main()
{
	double a=2.5;
	double b=3.5;
	cout<<"a+b="<<add(a,b)<<endl; // 模板实参推断
	cout<<"a+b="<<add<int>(a,b);  // 显式指定参数类型
}

显式实例化

显式实例化与前面的隐式实例化不同的是:实例化的时机不同。在我们写好一个函数模板后,如果我们能确定某个函数在接下来的业务逻辑中一定会被用到,则我们可以在这时候抢先实例化出这个函数。这样就比较快速,从而省去运行阶段创建这个函数的时间。

template<typename T>
void Swap(T&, T&)
{
	T temp;
	temp=a;
	a=b;
	b=temp;
}

template void Swap<int>(int&,int&);

int main()
{
	//.................
	.......代码段........//
}

当使用关键字template并指出所需类型来声明类时,编译器将生成函数声明的实例化。声明必须位于模板定义所在的作用域中。虽然没有创建或提及函数对象,编译器也将生成函数声明(包括方法定义)。但是,在实际使用时,会提示找不到Swap函数定义

特例化

有时候,尽管你的模板支持int,double,float,char…等等数据类型,但是等到下文去用的时候发现,虽然这个模板可以处理百分之九十的东西,但是总是存在一些例外是前文定义的模板所不能支持的,诚然,这个时候我们就要特殊情况特殊处理了。这种特殊情况特殊处理的方式就是C++里的特例化。
有时候,可能需要在为特殊类型实例化时,对模板进行修改,使其行为不同。在这种情况下,可以提供一个模板特例化。当特例化模板和通用模板都与实例化请求匹配时,编译器将优先使用特例化版本。

// 通用模板
template<typename T>
void Swap(T&, T&)
{
	T temp;
	temp=a;
	a=b;
	b=temp;
}
// 特例化模板
struct job
{
	char name[Max];
	double salary;
	int floor;
};

template <> void Swap(job& a, job& b)
{
	int temp1;
	temp1 = a.floor;
	a.floor = b.floor;
	b.floor = temp1;
	//
	double temp2;
	temp2 = a.salary;
	a.salary = b.salary;
	b.salary = temp2;
}

部分特例化(只有类模板可用)

部分特例化也是特例化的一种方式。处理的场景也跟前面差不多。那么为什么叫部分特例化呢?前面的特例化里,我们的模板参数只有一个,如果我们对其进行特例化,就相当于对全部参数进行特例化;但是也有一些情况,我们会遇到需要多个参数的模板。而我们的使用场景可能仅仅需要我们对个别参数进行特殊处理,这时候我们就可以通过部分特例化,部分限制模板的通用性,仅对部分数据进行特殊处理:

//general template
template<class T1,class T2,class T3> class Trio{...};
//specialization with T3 set to T2
template<class T1,class T2> class Trio<T1,T2,T2>{...};
//specialization with T3 and T2 set to T1*
template<class T1> class Trio<T1,T1*,T1*>{...};

//给出上述声明,编译器将作出以下选择:
Trio<int,short,char*> t1;//use general template
Trio<int,short> t2;//use Trio<T1,T2,T2>
Trio<char,char*,char*> t3;//use Trio<T1,T1*.T1*>

编译器重载规则

一般来说调用函数的优先级:非模板函数 > 特例化的模板函数 > 通用模板函数。

Swap(e1,e2);      // 优先使用非模板函数 
Swap<int>(f1,f2); // 使用模板函数

特别地,加上尖括号相当隐式实例化,让编译器使用模板函数而不是非模板函数。

参考文献

https://blog.csdn.net/qq_41126898/article/details/114503219
https://blog.csdn.net/weixin_43717839/article/details/131320956
C++ Primer(第五版)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值