👍作者主页:进击的1++
🤩 专栏链接:【1++的C++初阶】
文章目录
- 一,非类型模板参数
- 二,模板特化
- 三,模板分离编译
一,非类型模板参数
模板参数分为类类型模板参数与非类型模板参数。
 类类型形参:出现在模板参数列表中,跟在class或typenam的后面的参数类型。
 非类型形参:就是用一个常量作为模板的一个参数,在模板中可将该参数当成常量来使用。要注意的是:此常量必须为整型。
 例:
template<class T,size_t N=100>
	class Array
	{
	public:
		void Print()
		{
			cout << "print" << endl;
		}
	private:
		T arr[N];
	 
	};

二,模板特化
模板特化有函数模板特化和类模板特化。
 函数模板特化:
 我们先来看代码:
namespace hyp
{
	template<class T1, class T2>
	bool less(T1& a, T2& b)
	{
		return a < b;
	}
	
	class Date
	{
	public:
		Date(int year, int month, int day)
			:_year(year)
			,_month(month)
			,_day(day)
		{}
			bool operator<(const Date& d)const
		{
			if (_year < d._year)
			{
				return true;
			}
			else if (_year == d._year)
			{
				if (_month < d._month)
				{
					return true;
				}
				else if (_month == d._month)
				{
					if (_day < d._day)
					{
						return true;
					}
					else
						return false;
				}
				else
					return false;
			}
			else
				return false;
		}
		void Print()
		{
			cout << "print" << endl;
		}
	private:
		int _year;
		int _month;
		int _day;
	};
}
	int main()
	{
		hyp::Date a1(2023, 7, 25);
		hyp::Date a2(2023, 7, 4);
		hyp::Date a3(2023, 7, 16);
		hyp::Date* p1 = &a1;
		hyp::Date* p3 = &a3;
		hyp::Date* p2 = &a2;
		cout << hyp::less(a1, a2);
		cout << hyp::less(p3, p2);
		return 0;
	}

 当我们要进行某些特殊的比较时就会发生以上这种情况—>当我们想通过指向对象的指针比较日期大小时,结果就会有问题,为了解决这种问题,就有了模板特化。
 解决上述问题,我们有如下代码:
template<class T>
	bool less(T& a, T& b)
	{
		return a < b;
	}
	template<>
	bool less<Date*>(Date*& a, Date*& b)
	{
		return *a < *b;
	}

 类模板特化:
 类模板特化又有:全特化与偏特化。
 全特化:
 全特化即将模板参数列表中的所有参数都确定化。
 我们直接来看代码:
template<class T1, class T2>
	class Date
	{
	public:
		void Print()
		{
			cout << "template<class T1,class T2>" << endl;
		}
	private:
		T1 a;
		T2 b;
	};
	template<>
	class Date<int,char>
	{
	public:
		void Print()
		{
			cout << "template<int,char>" << endl;
		}
	private:
		int a;
		char b;
	};
}
	int main()
	{
		hyp::Date<int, int> d1;
		d1.Print();
		hyp::Date<int, char> d2;
		d2.Print();
		hyp::Date<double, char> d3;
		d3.Print();
		return 0;
	}

偏特化:
 偏特化即对模板参数进一步进行条件限制的特化版本。
 其有两种表现方式,先来看第一种:
template<class T1, class T2>
	class Date
	{
	public:
		void Print()
		{
			cout << "template<class T1,class T2>" << endl;
		}
	private:
		T1 a;
		T2 b;
	};
	template<class T1>
	class Date<T1,char>
	{
	public:
		void Print()
		{
			cout << "template<T1,char>" << endl;
		}
	private:
		T1 a;
		char b;
	};

 在上述代码中,我们将第二个参数特化为char。
 这种表现方式,我们叫做部分特化。
 接下来来看第二种:
template<class T1, class T2>
	class Date
	{
	public:
		void Print()
		{
			cout << "template<class T1,class T2>" << endl;
		}
	private:
		T1 a;
		T2 b;
	};
	template<class T1,class T2>
	class Date<T1*,T2*>
	{
	public:
		void Print()
		{
			cout << "template<T1*,T2*>" << endl;
		}
	private:
		T1 a;
		T2 b;
	};

 此种偏特化,对模板参数进行了更进一步的限制。
三,模板分离编译
我们假设有以下场景
 

 当我们运行时,会发现链接错误。这是为什么呢?
 在进行预处理时,我们的头文件会展开,在编译时,stu.c文件中的func先会去找有没有这个函数,在预处理阶段,头文件已经在我们的stu.c中展开,因此编译器就认为我们有这个函数,所以会根据某中规则形成符号记录在符号表中。而在func.c文件中编译器没有看到对模板函数的实例化,因此不会产生具体的func函数。所以在链接阶段时,我们在符号表中找不到对应的func函数,因此就会发生链接错误。
解决办法就是将函数的声明与定义放在一起,或者是模板定义的位置显式实例化,还可以使用函数的特化。
template<class T>
int func(T a)
{
	return 0;
}
template<>
int func<int>(int a)
{
	return 0;
}







![[元带你学: eMMC协议 28] eMMC 上电时序 | eMMC 上电指南](https://img-blog.csdnimg.cn/20200411195400795.png)











