c++模板2

非类型模板参数

模板的参数类型有2种:类型参数和非类型参数,类型参数一般用class或typename关键字修饰;非类型参数就是用一个常量作为模板的参数,在模板中可以直接使用该参数,需要注意的是,浮点数、类对象和字符串常量是不允许作为模板的非类型参数的,同时该参数必须在编译期间就可以确认结果。

template<class T,size_t i = 10>
class Test
{
//...
};

类模板的特化

通过使用模板,我们可以实现一些与类型无关的代码,但对于一些特殊的类型,我们可能需要进行特殊处理,这就需要用到模板的特化。

template<class T>
bool Compare(const T data1, const T data2)
{
	return data1<data2;
}

int main()
{
	int data1=1;
	int data2=2;
	int* p1=&data1;
	int* p2=&data2;
	
	Compare(data1,data2);//正常使用
	Compare(p1, p2);//我们希望比较指针指向的值的大小,而不是指针的大小
}

模板特化就是在原模版的基础上,对特殊类型进行特殊化的实现方式,分为函数模板特化和类模板特化。
一.函数模板特化:

//原模版
template<class T>
bool Compare(const T data1, const T data2)
{
	return data1<data2;
}

//函数模板特化
//必须要有一个原模版
template<>
bool Compare<int*>(const int* data1, const int* data2)
{
	return data1<data2;
}

由于使用函数模板特化函数类型容易匹配不上,因此我们不建议使用函数模板特化,而是直接将该函数给出,这种实现方式简单明了,且可读性也高。

bool Compare(const int* data1, const int* data2)
{
	return data1<data2;
}

当参数类型匹配时,编译器优先使用我们给出的函数,不会去走函数模板特化。

二.类模板特化:
1.全特化
将模板参数列表的所有参数确定化就是全特化

template<class T1, class T2>
class Test
{
	//...
};

//全特化
template<>
class Test<int, char>
{
	//...
};

2.偏特化(半特化)
偏特化有两种表现方式:
①部分特化,即将类模板参数列表的部分参数进行特化:

template<class T1>
class Test<T1, char>
{
	//...
};

②还有一种偏特化是对参数做更进一步的限制,比如参数类型是指针或者引用

template<class T1, class T2>
class Test<T1*, T2*>
{
	//...
};

模板的分离编译

一个工程可能会有许多源文件,我们一般都会将声明和定义进行分离,把声明放在头文件中,定义则放在源文件里面,然后将每个源文件单独编译生成目标文件(头文件不参与编译),最后将目标文件进行链接就形成可执行程序。但如果我们将模板的声明和定义进行分离,编译器在链接时会出错。
在这里插入图片描述

在test.cpp中,只有模板函数的定义,没有模板函数的实例化,因此编译器不会生成具体的函数,也就不存在该模板函数实例化后的函数地址,main.cpp调用fun(int.int)函数,但在链接期间找不到函数地址,因此出错。
对于以上问题,我们有两种解决方案:
1.在模板定义位置进行显示实例化
这种方法简单粗暴,但不实用,我们不推荐使用
2.将声明和定义放到同一个头文件中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值