首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【c++】模板进阶

【c++】模板进阶

作者头像
用户11972710
发布2025-12-30 19:19:43
发布2025-12-30 19:19:43
110
举报

在前面我们学习了模板的基础用法【c++】 模板初阶-CSDN博客初步认识了函数模板和类模板,接下来让我们看看模板还有哪些进阶的应用。

非类型模板参数

之前我们用到的模板全都使用了类型参数

类型参数:表示某种数据类型(如 intdouble、自定义类等)。

非类型参数:表示常量值(如整数、指针、引用等)。

这样模板的每一个类型参数都要由我们传入的数据类型在实例化的时候由编译器确定。在一些特定的情况,会用到常量;如我们需要一个定长的数组时。控制数组长度的类型时确定的(如size_t),这样我们只设置一个类型参数就可以了。

代码语言:javascript
复制
namespace xian
{

	//定义一个模板类型的定长数组

	template<typename T,size_t N>
	class array
	{
	public:
		T& operator[](size_t n)
		{
			return _array[n];
		}
		const T& operator[](size_t n) const
		{
			return _array[n];
		}
		size_t size()
		{
			return _size;
		}
		bool empty()
		{
			return 0 == _size;
		}
	private:
		T _array[N];
		size_t _size;
	};

}

注意:非类型模板参数只能用于整型;不支持浮点数,类对象和字符串。c++20之后可以支持double作非类型模板参数。

非类型模板参数支持缺省值:

代码语言:javascript
复制
	template<size_t N = 10>
	class Stack
	{
	private:
		int a[N];
		int _top;
	};
	int main()
	{
		//Stack s0;  这种写法要c++20以后才支持
		Stack<> s1;  //我们还是用这种写法的好

	}

模板的特化

函数模板的特化

代码语言:javascript
复制
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
	return left < right;
}

int main()
{
	cout << Less(1, 2) << endl;
	Date d2(2022, 7, 8);
	Date d1(2022, 7, 7);
	
	cout << Less(d1, d2) << endl;//可以正常判断
	Date* p2 = &d2;
	Date* p1 = &d1;
	
	cout << Less(p1, p2) << endl; //会直接比较指针
	return 0;
}

根据地址比较大小,而地址的申请时随机的,这样结果是不能确定的。对于这种有特殊情况的可以使用模板的特化,把特殊情况单独拿出来处理。

代码语言:javascript
复制
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
	return left < right;
}

// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
	return *left < *right;
}
int main()
{
	cout << Less(1, 2) << endl;
	Date d2(2022, 7, 8);
	Date d1(2022, 7, 7);
	
	cout << Less(d1, d2) << endl;//可以正常判断
	Date* p2 = &d2;
	Date* p1 = &d1;
	
	cout << Less(p1, p2) << endl; //会直接比较指针
	return 0;
}

有特化后的类之后,会直接使用特化后的类。

总结:

  • 主模板:定义通用的函数模板。
  • 特化版本:为特定类型提供定制化实现。
  • 调用:编译器根据参数类型自动选择主模板或特化版本。
  • 注意事项:特化版本的函数签名必须与主模板一致,且不支持偏特化。

大多数时候,我们都选择简单的方法直接把特殊的情况函数直接给出而不是使用特化。使用特化容易出错,一般不要使用函数模板特化

类模板的特化

全特化

全特化就是将模板参数全部特化

代码语言:javascript
复制
//全特化
template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
template<>
class Data<int, char>
{
public:
	Data() { cout << "Data<int, char>" << endl; }
private:
	int _d1;
	char _d2;
};
void TestVector()
{
	Data<int, int> d1;
	Data<int, char> d2;
}
偏特化

偏特化是对模板参数部分特化,不仅仅是列出部分模板参数的具体类型,也可能是对原始模板作一些限制。

偏特化一共有两种表现方式:

部分特化
代码语言:javascript
复制
template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
//部分特化
template<class T1>
class Data<T1, char>
{
public:
	Data() { cout << "Data<int, char>" << endl; }
private:
	T1 _d1;
	char _d2;
};
void TestVector()
{
	Data<int, int> d1;
	Data<int, char> d2;
}


template <class T1>
class Data<T1, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};
限制参数
代码语言:javascript
复制
template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

//限制传入的数据类型为指针

template<class T1, class T2>
class Data<T1*,T2*>
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

//限制传入的数据类型为引用
template<class T1, class T2>
class Data<T1&, T2&>
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 非类型模板参数
  • 模板的特化
    • 函数模板的特化
    • 类模板的特化
      • 全特化
      • 偏特化
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档