【C++】模板进阶

【C++】模板进阶

1.非类型模板参数

先回忆下之前学过的模板

Add为一个类型形参模板,图中不管是将a,b还是c,d传参到Add函数中使用都会自动识别出数据类型并进行处理。

接下来让我们看一下这串代码,并思考:我们知道在这个我们自己写的array类中,里面的成员变量使用了指针实现了动态数组,那我们如果需要的是静态数组呢,该如何修改代码?

image-20230411212059746

部分朋友可能会想到使用宏定义 #define N 10 ,T* array–>T array[N] 并且按照应用需求时刻来修改N值来实现对array静态数组的实现

image-20230411212834070

但是如果我们面对的是这样的情况:a1数组中需要存放100个int类型的数据,a2数组中需要存放1000个double类型的数据,a3数组中需要存放10000个float类型数据。 我们使用这个宏定义还能解决问题吗?

接下来介绍我们今天将要学习的内容:非类型模板参数

模板参数分类类型形参与非类型形参。
类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用

image-20230411213723051

如此使用非类型模板参数,就很好解决了上述问题

image-20230411213941902

注意:

1.浮点数、类对象以及字符串是不允许作为非类型模板参数的。

2.非类型的模板参数必须在编译期就能确认结果

2.模板的特化

2.1概念

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理。比如:实现了一个专门用来进行小于的函数

image-20230411221647669

在这里,如果按照我们的预期,代码执行结果应为:0,0,0

image-20230411221801885

0,0,1? 这里为什么会出现1。大家可以很明显的看到p1,p2分别为地址,并不能直接进行比较,那我们该如何解决该问题呢?

此时,就需要对模板进行特化。即:在原模版类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化与类模板特化

2.2函数模板特化

函数模板的特化步骤:

1.必须要先有一个基础的函数模板

2.关键字template后面接一对空的尖括号<>

3.函数名后跟一对尖括号,尖括号中指定需要特化的类型

4.函数形参表:必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报错

接下来,我们就对Less函数模板进行特化,处理日期类对象地址不能进行正确比较的问题

image-20230411223037873

cout <<Less(p1,p2)<<endl; 这行代码会调用特化之后的版本,而不走模板生成。

注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都将函数直接给出。

bool Less(Date* left,Date* right)
{
 	return *left>*right;
}

这种实现简单明了,代码的可读性高,容易书写,因为对于一些参数类型辅助的函数模板,特化时特别给出,因此函数模板不建议特化。

2.3类模板特化

2.3.1 全特化

全特化是将模板参数列表中所有的参数都确定化

template<class T1, class T2>
class Date
{
public:
	Date()
	{
		cout << "Date<T1,T2>" << endl;
	}

private:
	T1 _t1;
	T2 _t2;
};
// 全特化
template<>
class Date<int ,char>
{
	Date()
	{
		cout << "Date<int,char>" << endl;
	}
private:
	int _t1;
	char _t2;
};
2.3.2偏特化

偏特化:任何针对模版参数进一步进行条件限制设计的特化版本

1.部分特化

template<class T1, class T2>
class Date
{
public:
	Date()
	{
		cout << "Date<T1,T2>" << endl;
	}

private:
	T1 _t1;
	T2 _t2;
};
//偏特化
template<class T1>
class Date<T1,char>
{
	Date()
	{
		cout << "Date<T1, char>" << endl;
	}
private:
	T1 _t1;
	char _t2;
};

2.参数更进一步的限制

偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。

// 参数类型进一步限制
template<class T1, class T2>
class Date<T1*, T2*>
{
public:
	Date()
	{
		cout << "Data<T1*, T2*>" << endl; 
	}
};

template<class T1, class T2>
class Date<T1&, T2&>
{
public:
	Date()
	{ 
		cout << "Data<T1&, T2&>" << endl; 
	}
};
2.3.3 类模板特化应用示例
template<class T1, class T2>
class Date
{
public:
	Date()
	{
		cout << "Date<T1,T2>" << endl;
	}

private:
	T1 _t1;
	T2 _t2;
};
// 全特化
template<>
class Date<int ,char>
{
public:
	Date()
	{
		cout << "Date<int,char>" << endl;
	}
};
//偏特化
template<class T1>
class Date<T1,char>
{
public:
	Date()
	{
		cout << "Date<T1, char>" << endl;
	}
};
// 参数类型进一步限制
template<class T1, class T2>
class Date<T1*, T2*>
{
public:
	Date()
	{
		cout << "Data<T1*, T2*>" << endl; 
	}
};

template<class T1, class T2>
class Date<T1&, T2&>
{
public:
	Date()
	{ 
		cout << "Data<T1&, T2&>" << endl; 
	}
};
int main()
{
	Date<int, int> d1;
	Date<double, double> d2;
	Date<double, char> d3;
	Date<char, char> d4;

	Date<char*, char*> d5;
	Date<char, int*> d6;
	Date<double*, int*> d7;

	Date<double&, int&> d8;
    return 0;
}

image-20230411231643756

3.总结

【优点】

1.模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生

2.增强了代码的灵活性

【缺陷】

1.模板会导致代码膨胀问题,也会导致编译时间变长

2.出现模板编译错误时,错误信息非常凌乱,不易定位错误

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

希德学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值