C++学习第十一天(模版进阶)

1、非类型模版参数

模版参数分为类类型形参和非类型形参

类类型形参:出现在参数列表中,跟在class或者typename之类的参数类型名称

非类型形参:就是用一个常量作为类(函数)模版的一个参数,在类(函数)模版中可将该参数当成常量来使用

namespace bite
{
	//定义一个模版类型的静态数组
	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;
	};
}

 注意:

  • 浮点数、类对象以及字符串是不允许作为非类型模版参数的
  • 非类型的模版参数必须在编译期就能确认结果

 2、模版的特化

概念

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

template<class T>
bool Less(T left, T right)
{
	return left < right;
}

int main()
{
	cout << Less(1, 2) << endl; //结果正确
	Date d1(2022, 7, 7);
	Date d2(2022, 7, 8);
	cout << Less(d1, d2) << endl;//结果正确
	Date* p1 = &d1;
	Date* p2 = &d2;
	cout << Less(p1, p2) << endl;//结果错误

	return 0;
}

可以发现,Less在绝大多数情况可以正常比较,但是比如在上述情况就会出现错误,

因为Less内部并没有比较p1和p2指向的对象内容,而比较的是p1和p2指针的地址,就无法达到预期而错误

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

函数模版特化

函数模版的特化步骤:

  1. 必须要先有一个基础的函数模版
  2. 关键字template后接上一对空的尖括号<>
  3. 函数名后跟上一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参表:必须要和模版函数的基础参数类型完全相同,不然编译器会出现一些奇怪的错误
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 d1(2022, 7, 7);
	Date d2(2022, 7, 8);
	cout << Less(d1, d2) << endl;//结果正确
	Date* p1 = &d1;
	Date* p2 = &d2;
	cout << Less(p1, p2) << endl; //结果正确
	return 0;
}

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

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

 类模版特化

全特化

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

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

template<>
class Date<int, char>
{
public:
	Date() { cout << "Date<int, char>" << endl; }
private:
	int _d1;
	int _d2;
};

int main()
{
	Date<int, int> d1;
	Date<int, char> d2;
	return 0;
}

 偏特化

偏特化:任何针对模版参数进一步进行条件限制的特化版本,比如以下模版类


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

偏特化有以下两种特化方式:

1、部分特化:将模版参数类表中的一部分参数特化

// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};

2、参数更进一步的限制

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

//两个参数偏特化为指针类型
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;
};

int main()
{
	Data<double, int> d1;//调用特化的int版本
	Data<int, double> d2;//调用基础的模版
	Data<int*, int*> d3;//调用特化的指针版本
	Data<int&, int&> d4(1, 2);//调用特化的引用版本
	return 0;
}

类模版特化应用实例

有如下专门用来按照小于比较的类模版Less

template<class T>
//仿函数
struct Less
{
	bool operator()(const T& x, const T& y)const
	{
		return  x < y;
	}
};

int main()
{
	Date d1(2022, 7, 7);
	Date d2(2022, 7, 3);
	Date d3(2022, 7, 9);
	vector<Date> v1;
	v1.push_back(d1);
	v1.push_back(d2);
	v1.push_back(d3);
	//可以直接排序,结果是日期排序
	sort(v1.begin(), v1.end(), Less<Date>());
	vector<Date*> v2;
	v2.push_back(&d1);
	v2.push_back(&d2);
	v2.push_back(&d3);
	//可以直接排序,结果错误日期还不是升序,而v2中放的地址是升序
	//此处需要在排序过程中,让sort比较v2中存放地址指向的日期对象
	//但是走Less模版,sort在排序时实际比较的是v2中指针的地址,因此无法达到预期
	sort(v2.begin(), v2.end(), Less<Date*>());
	return 0;
}

我们可以发现,对于日期对象可以直接排序,并且结果是正确的。但是如果待排序元素是指针,结果就不一定正确。因为sort最终按照Less模版中方式比较,所以只会比较指针,而不是比较指针指向空间中内容,此时可以使用类版本特化来处理问题

template<>
struct Less<Date*>
{
	bool operator()(Date* x, Date* y) const
	{
		return *x < *y;
	}
};

此时运行以上代码就是正确的 

3、模版分离编译 

什么是分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式

 模版的分离编译

假设有以下场景,模版的声明与定义分离开,在头文件中进行声明,在源文件中完成定义:

// a.h
template<class T>
T Add(const T& left, const T& right);
// a.cpp
template<class T>
T Add(const T& left, const T& right)
{
 return left + right;
}
 
// main.cpp
#include"a.h"
int main()
{
 Add(1, 2);
 Add(1.0, 2.0);
 
 return 0;
}

此时编译器会报错:无法解析的外部符号。因为这两个函数没有实例化生成具体代码,因此链接时报错。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CV每日论文--2024.5.7

1、Vibe-Eval: A hard evaluation suite for measuring progress of multimodal language models 中文标题&#xff1a;Vibe-Eval: 一个测量多模态语言模型进度的严格评估套件 简介&#xff1a;本文介绍了一种新的开放评估基准 Vibe-Eval,用于评估多模态对话模型的性能。 Vibe…

C++学习笔记——对仿函数的理解

文章目录 思维导图仿函数出现的逻辑仿函数使用上的巧妙 仿函数的本质仿函数的优势仿函数语法的巧妙 思维导图 仿函数出现的逻辑 我们在学习stack时会遇到一些新的问题&#xff0c;这些问题需要我们使用非类型模板参数去解决&#xff0c;即我们需要在设计类时需要有一个途径去快…

Mujoco210和Mujoco-py在 Ubuntu22.04 下的安装

mujoco和mujoco-py的关系&#xff1a;mujoco是一个物理引擎&#xff0c;主要应用于强化学习和最优化控制领域。mujoco-py是mujoco编程的 Python 接口&#xff0c;由OpenAI Gym开发&#xff0c;可以使用mujoco_py方便地调用mujoco的API。 mujoco官网&#xff1a; https://mujoco…

Elementui的el-footer标签使用报错

Elementui的el-footer标签使用报错 其余标签的使用没有报错信息 el-footer的报错信息 原因: ​ 警告信息表示 Vue 不识别 <el-footer> 解决方式: 在组件中进行引入和暴露

编程入门(六)【Linux系统基础操作二】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;文件与目录的操作命令cd change directory的缩…

代码随想录算法训练营Day12 | 二叉树理论基础、递归遍历、迭代遍历、统一迭代

今日收获&#xff1a; 二叉树的递归遍历二叉树的迭代遍历&#xff0c;中序的迭代法和前、后序不一样二叉树的统一迭代法主要是用了标记法来实现&#xff08;要处理的节点放入栈之后&#xff0c;紧接着放入一个空指针作为标记&#xff09; 二叉树理论基础篇 题目分类 题目分…

ICode国际青少年编程竞赛- Python-1级训练场-多变量应用

ICode国际青少年编程竞赛- Python-1级训练场-多变量应用 1、 a 1 b 2 for i in range(4):Spaceship.step(a)Dev.step(b)Dev.step(-b)a a 1b b 12、 a 2 b 5 for i in range(3):Spaceship.turnLeft()Spaceship.step(a)Spaceship.turnRight()Spaceship.step(b)a a …

在线民宿预约系统:景区住宿预订新体验

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

简述 BIO 、NIO 模型

BIO : 同步阻塞I/O&#xff08;Block IO&#xff09; 服务器实现模式为每一个连接一个线程&#xff0c;即客户端有连接请求时服务器就需要启动一个线程进行处理&#xff0c;如果这个连接不做任何事情会造成不必要的线程开销&#xff0c;此处可以通过线程池机制进行优化。 impo…

分享5款PDF编辑软件

PDF编辑不易&#xff0c;有需要的朋友可以试试这5款专业软件&#xff0c;每一个都能直接在PDF文件上编辑&#xff0c;不同的软件对PDF可编辑的范围不同&#xff0c;大家可以按需求选用。 1.edge浏览器 Edge浏览器不仅是浏览网页的得力助手&#xff0c;还悄然成为了轻量级PDF管…

【Stream 流】通过一个例子看遍所有Stream API使用场景

前言 上篇文章记录了方法引用&#xff0c;Lambda表达式等基础的知识点&#xff0c;这篇文章主要结合课设项目详细介绍Stream 流的API以及它的主要场景。 Stream API作用 在Java 8及其以后的版本中&#xff0c;Stream API为处理集合数据提供了强大而灵活的功能。有了Stream AP…

Petalinux的使用——定制Linux系统

文章目录 配置petalinux运行环境petalinux设计流程 配置petalinux运行环境 Petalinux的安装在文章Ubuntu镜像源的更改及其Petalinux的安装中已经介绍&#xff0c;下面介绍petalinux运行环境的配置过程。 进入到petalinux的安装路径下&#xff0c;使用下面的命令对petalinux的运…

类和对象-Python-第一部分

初识对象 使用对象组织数据 class Student:nameNonegenderNonenationalityNonenative_placeNoneageNonestu_1Student()stu_1.name"林军杰" stu_1.gender"男" stu_1.nationality"中国" stu_1.native_place"山东" stu_1.age31print(stu…

《视觉十四讲》例程运行记录(2)——运行ch4的例程评估轨迹误差

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、运行ch4的example1. 编译例程2. 运行报错(1) 报错一(2) 报错二 一、运行ch4的example 1. 编译例程 (1) 在slambook2/ch4/example目录下&#xff0c;创建build…

五月节放假作业讲解

目录 作业1&#xff1a; 问题&#xff1a; 结果如下 作业2&#xff1a; 结果: 作业1&#xff1a; 初始化数组 问题&#xff1a; 如果让数组初始化非0数会有问题 有同学就问了&#xff0c;我明明已经初始化定义过了&#xff0c;为啥还有0呀 其实这种初始化只会改变第一个…

【嵌入式笔试题】网络编程笔试题

非常经典的笔试题。 2.网络编程(29道) 2.1列举一下OSI协议的各种分层。说说你最熟悉的一层协议的功能。 ( 1 )七层划分为:应用层、表示层、会话层、传输层、网络层、数据链路层、物理 层。 ( 2 )五层划分为:应用层、传输层、网络层、数据链路层、物理层。 ( 3 )…

视频改字祝福/豪车装X系统源码/小程序uniapp前端源码

uniapp视频改字祝福小程序源码&#xff0c;全开源。创意无限&#xff01;AI视频改字祝福&#xff0c;豪车装X系统源码开源&#xff0c;打造个性化祝福视频不再难&#xff01; 想要为你的朋友或家人送上一份特别的祝福&#xff0c;让他们感受到你的真诚与关怀吗&#xff1f;现在…

VALSE 2024年度进展评述内容分享-视觉基础大模型的进展

2024年视觉与学习青年学者研讨会&#xff08;VALSE 2024&#xff09;于5月5日到7日在重庆悦来国际会议中心举行。本公众号将全方位地对会议的热点进行报道&#xff0c;方便广大读者跟踪和了解人工智能的前沿理论和技术。欢迎广大读者对文章进行关注、阅读和转发。文章是对报告人…

探无止境,云游未来 | “游戏出海云”发布

4月28日下午&#xff0c;2024中国移动算力网络大会之“游戏出海”分论坛在江苏省苏州金鸡湖国际会议中心圆满落幕。 此次论坛由中国移动海南公司主办&#xff0c;中国移动通信集团政企事业部、中国移动云能力中心、中国移动国际公司共同协办。海南省工业与信息化厅副厅长黄业晶…

【栈】Leetcode 1047. 删除字符串中的所有相邻重复项

题目讲解 1047. 删除字符串中的所有相邻重复项 算法讲解 使用栈这个数据结构&#xff0c;每一次入栈的时候观察此时的字符和当前栈顶字符是否相等&#xff0c;如相等&#xff1a;栈顶出栈&#xff1b;不相等&#xff1a;入栈 class Solution { public:string removeDuplica…
最新文章