【C++】模板进阶

文章目录

  • 【C++】模板进阶
    • 1.非类型模板参数
    • 2.模板的特化
      • 2.1概念
      • 2.2函数模板特化
      • 2.3类模板特化
        • 2.3.1 全特化
        • 2.3.2偏特化
        • 2.3.3 类模板特化应用示例
    • 3.总结

【C++】模板进阶

1.非类型模板参数

先回忆下之前学过的模板

【C++】模板进阶_第1张图片

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

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

【C++】模板进阶_第2张图片

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

【C++】模板进阶_第3张图片

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

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

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

【C++】模板进阶_第4张图片

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

image-20230411213941902

注意:

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

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

2.模板的特化

2.1概念

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

【C++】模板进阶_第5张图片

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

【C++】模板进阶_第6张图片

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

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

2.2函数模板特化

函数模板的特化步骤:

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

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

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

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

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

【C++】模板进阶_第7张图片

cout <

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

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" << endl;
	}

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

2.3.2偏特化

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

1.部分特化

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

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

2.参数更进一步的限制

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

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

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

2.3.3 类模板特化应用示例

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

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

template<class T1, class T2>
class Date<T1&, T2&>
{
public:
	Date()
	{ 
		cout << "Data" << 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;
}

【C++】模板进阶_第8张图片

3.总结

【优点】

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

2.增强了代码的灵活性

【缺陷】

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

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

你可能感兴趣的:(C++学习,c++,算法,开发语言)