C++:模板特化 非类型模板参数

news2025/1/19 14:38:46

目录

1.非类型模板参数

 2.模板特化

2.1 为什么需要模板特化

2.2 函数模板特化

2.3 类模板特化

1.全特化

2.偏特化

1.部分特化

 2.参数更进一步的限制


1.非类型模板参数

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

我们可以创建一个模板类,其中包含一个非类型参数作为数组的大小,这样可以在编译时就确定数组的大小,而不是在运行时动态分配内存。 

#include<iostream>
using namespace std;
namespace wjc
{
	// 定义一个模板类型的静态数组
	template<class T, size_t N = 10>
	class array
	{
	public:
		T& operator[](size_t index) { return _array[index]; }
		const T& operator[](size_t index)const { return _array[index]; }

		size_t size()const { return _size; }
		bool empty()const { return 0 == _size; }

	private:
		T _array[N];
		size_t _size;
	};
}
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的
2. 非类型的模板参数 必须在编译期就能确认结果

 2.模板特化

2.1 为什么需要模板特化

通常情况下, 使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果 ,需要特殊处理。
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
	return left < right;
}
int main()
{
	int a = 10;
	int b = 20;
	int* p1 = &a;
	int* p2 = &b;
	cout << Less(p1, p2) << endl;
	return 0;
}

运行发现比较的并不是预想中的a<b  而是比较的两个指针的大小。

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

2.2 函数模板特化

函数模板的特化步骤:
1. 必须要先有一个基础的函数模板
2. 关键字 template 后面接一对空的尖括号 <>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
	return left < right;
}
// 对Less函数模板进行特化
template<>
bool Less<int*>(int* left, int* right)
{
	return *left < *right;
}
int main()
{
	int a = 10;
	int b = 20;
	int* p1 = &a;
	int* p2 = &b;
	cout << Less(p1, p2) << endl;
	return 0;
}

得到正确的比较结果,调用了特化后的函数。

2.3 类模板特化

1.全特化

全特化即是将模板参数列表中所有的参数都确定化。
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;
}

可以使用C++全特化来为特定类型的数据结构提供特定的实现,以提高程序的效率。另外,也可以使用C++全特化来为特定的参数提供特殊的实现,以满足特定的需求。

2.偏特化

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

偏特化通常用于处理特定类型或特定条件下的情况,以提供更具体的实现。这使得模板可以更灵活地适应不同的情况,提高了代码的可复用性和可扩展性。

假设有一个模板类,可以通过偏特化来为指针类型提供特殊的实现,或者为特定的数据结构提供特殊的处理。这样可以根据具体的需求,为模板提供更具体的实现,而不必对整个模板进行特化。

偏特化有以下两种表现方式;
1.部分特化

将模板参数类表中的一部分参数特化

// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:
 Data() {cout<<"Data<T1, int>" <<endl;}
private:
 T1 _d1;
 int _d2;
};
 2.参数更进一步的限制
偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。
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, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};
//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }

private:
	T1 _d1;
	T2 _d2;
};
//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:
	Data(const T1& d1, const T2& d2)
		: _d1(d1)
		, _d2(d2)
	{
		cout << "Data<T1&, T2&>" << endl;
	}

private:
	const T1& _d1;
	const T2& _d2;
};

void test2()
{
	Data<double, int> d1; // 调用特化的int版本
	Data<int, double> d2; // 调用基础的模板 
	Data<int*, int*> d3; // 调用特化的指针版本
	Data<int&, int&> d4(1, 2); // 调用特化的指针版本
}
C++偏特化是模板编程中的重要特性,可以帮助我们根据具体的需求为模板提供更灵活和具体的实现。
模板特化的好处

提高性能:通过特化模板,可以为特定的类型或参数提供更高效的实现,从而提高程序的性能。

灵活性:模板特化允许程序员根据具体的需求为模板提供定制的实现,使得代码更加灵活和可定制化。

可读性:特化模板可以使代码更具可读性,因为特定类型或参数的实现可以更直观和清晰。

可复用性:通过特化模板,可以在不同的情况下重复使用通用的代码结构,从而提高代码的可复用性。

扩展性:模板特化可以使得代码更易于扩展和维护,因为可以根据需要添加新的特化实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1416277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java正则校验,手机号,邮箱,日期格式,时间格式,数字金额两位小数

java正则校验&#xff0c;手机号&#xff0c;邮箱&#xff0c;日期格式&#xff0c;时间格式&#xff0c;数字金额两位小数 3.58是否为金额&#xff1a;true 3.582是否为金额&#xff1a;false 1284789qq.com是否为email&#xff1a;true 1284789qq.com是否为email&#xff1…

01_Anaconda环境搭建

概述 Anaconda包含了许多常用的科学计算和数据分析的库和工具。通过Anaconda&#xff0c;用户可以更方便地安装、管理和更新这些库和工具&#xff0c;从而提高工作效率。 Anaconda还提供了一个名为conda的包管理器&#xff0c;可以帮助用户方便地安装、管理和更新这些库和工具…

linux 基于科大讯飞的文字转语音使用

官方文档地址&#xff1a;离线语音合成 Linux SDK 文档 | 讯飞开放平台文档中心 一、SDK下载 1、点击上面官方文档地址的链接&#xff0c;可以跳转到以下界面。 2、点击“普通版”&#xff0c;跳转到以下界面。 3、点击“下载”跳转到以下界面 4、最后&#xff0c;点击“SDK下…

AI编译器的前端优化策略

背景 工作领域是AI芯片工具链相关&#xff0c;很多相关知识的概念都是跟着项目成长建立起来&#xff0c;但是比较整个技术体系在脑海中都不太系统&#xff0c;比如项目参与中涉及到了很多AI编译器开发相关内容&#xff0c;东西比较零碎&#xff0c;工作中也没有太多时间去做复盘…

Linux 增加 SWAP 空间

一、需求 通过阿里云启动项目时&#xff0c;使用Vuepress build编译静态页面时内存需要800MB&#xff0c;导致内存不够&#xff0c;因此考虑使用swap方式&#xff0c;置换一些内存资源存放swap磁盘。 [rootxxx myblog]# npm run docs:dev> myblog1.0.0 docs:dev > vuep…

分类预测 | Matlab实现DT决策树多特征分类预测

分类预测 | Matlab实现DT决策树多特征分类预测 目录 分类预测 | Matlab实现DT决策树多特征分类预测分类效果基本描述程序设计参考资料分类效果

ParaView更改RenderView背景颜色

如下图&#xff0c;这种蓝紫色是ParaView的RenderView默认设置颜色 想要更改背景颜色&#xff0c;需要打开Properties如果想要更改渲染物体的颜色&#xff0c;需要打开Color Map Editor 打开方式&#xff1a; 在页面上方工具栏的地方右键&#xff0c;勾选Properties和Color …

stable diffusion学习笔记——文生图(二)

LORA和Embeddings都可以对画面内容进行调整。目前LORA主要用来定义画面特征&#xff0c;如具体的人物&#xff0c;衣物&#xff0c;画风等。Embeddings目前主要用于反面提示词中&#xff0c;用来避免错误的画面表现。 LORA lora的全称为&#xff1a;低秩适应模型。lora的基本…

算法,不再难学!揭秘两款让你迅速学会算法的在线工具

1. VisuAlgo VisuAlgo 是一个由 Dr. Steven Halim 创立的在线平台,用于通过可视化的方式帮助学生和开发者理解和掌握各种复杂的数据结构和算法。该网站特别适合那些视觉学习者,也就是通过看图形、动画和演示来更好地理解概念的人。 以下是 VisuAlgo 的一些关键特点和功能: …

深兰科技入选亿欧《“制”敬不凡先锋榜·智能机器人Top10》榜单

日前&#xff0c;由亿欧协办的2023工博会工业智能化发展高峰论坛于上海成功举办&#xff0c;会上发布了《2023智能制造&#xff1a;“制”敬不凡先锋者》系列名单。深兰科技凭借在智能机器人开发中的技术创新和模式应用&#xff0c;入选《“制”敬不凡先锋榜——智能机器人Top1…

Java8-Stream 流基本应用-groupBy进行分组

groupBy进行分组 Testpublic void testStreamGroupBy(){List<UserInfoModel> resultnew ArrayList<>();for (int i 0; i < 10; i) {UserInfoModel usernew UserInfoModel();user.setUserId(i"");user.setUserName("kangshihang");result.a…

基于深度学习的狗狗类别检测

探索狗狗识别技术 引言1. 数据集介绍1.1 语境1.2 内容1.3 致谢 2. 项目背景与意义3. 项目实现流程3.1 数据处理与准备3.2 环境准备与工具安装3.3 模型配置与训练3.4 模型评估与预测3.5 模型推理与部署 4. 总结 服务 引言 随着人工智能技术的不断发展&#xff0c;图像识别已成为…

LabVIEW信号时间间隔测量

用LabVIEW软件平台开发一个用于测量两路信号时间间隔的系统。系统利用LabVIEW的数据采集和处理能力&#xff0c;能够准确测量并分析来自不同硬件板卡的信号时间间隔&#xff0c;这对于精确控制和数据分析至关重要。 系统主要由以下几部分组成&#xff1a;数据采集卡、信号处理…

【Linux】命名管道

文章目录 命名管道一、命名管道的原理二、命名管道的创建命令行中创建程序中创建 - mkfifo函数&#xff1a; 三、命名管道的使用命名管道实现server&client通信 四、匿名管道与命名管道的区别 命名管道 如果涉及到在文件系统中创建一个有名的管道&#xff0c;那么就是在使…

【c语言】详解操作符(下)

前言&#xff1a; 在上文中&#xff0c;我们已经学习了 原码、反码、补码、移位 操作符、移位操作符、位操作符、逗号表达式、下标访问[ ]、函数调用&#xff08; &#xff09;&#xff0c;接下来我们将继续学习剩下的操作符。 1. 结构成员访问操作符 1.1 结构体成员的直接访…

技术书评和笔记【01】脑机接口-电路与系统 【2020版】

前言: 荷兰作者,Amir Zjajo博士,毕业于荷兰代尔夫特理工大学,方向 面向移动健康的低功耗混合型号电路与系统,以及,面向认知的神经形态电路。 ,脑机接口 - 电路与系统一书,系统介绍了,脑机接口电路与系统的实现技术,尤其,提到了量产和设计的问题,难能可贵,摘录如…

预训练语言模型transformer

预训练语言模型的学习方法有三类&#xff1a;自编码&#xff08;auto-encode, AE)、自回归&#xff08;auto regressive, AR&#xff09;&#xff0c;Encoder-Decoder结构。 决定PTM模型表现的真正原因主要有以下几点&#xff1a; 更高质量、更多数量的预训练数据增加模型容量…

CSS--Emmet 语法

Emmet语法的前身是Zen coding,它使用缩写,来提高html/css的编写速度, Vscode内部已经集成该语法. 目录 1. 快速生成HTML结构语法 1.1 快速生成HTML结构语法 2. 快速生成CSS样式语法 2.1 快速生成CSS样式语法 1. 快速生成HTML结构语法 1.1 快速生成HTML结构语法 1. 生成标…

【C++】C++ 入门 — 命名空间,输入输出,函数新特性

C 1 前言2 命名空间2.1 概念引入2.2 开始使用2.3 投入应用 3 输入与输出3.1 基础知识3.2 开始使用3.3 注意局限 4 函数新特性4.1 缺省参数4.1.1 开始使用4.1.2 注意事项 4.2 函数重载4.2.1 开始使用4.2.2 如何实现 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读下…

仰暮计划|“老师说我其实很聪明,就是家里太穷了没条件,不然我现在也是……”

吴桂荣老人回忆录 在我外婆家的时候&#xff0c;我跟几位老奶奶坐在门口一起聊天&#xff0c;我询问她们是否能帮助我完成一份作业&#xff0c;她们笑着答应了&#xff0c;最后我选择了其中的一位老奶奶作为了解对象&#xff0c;她邀请我去家中交谈。通过了解&#xff0c;我得知…