再谈c++模板
前言
在前面我们曾经简单的介绍过c++的模板,但还并不全面,我们通过stl容器的学习加深了我们对c++这门语言的理解。那么今天我们就再来谈一谈c++模板,对模板再进行一点简单的补充
非类型模板参数
前面我们介绍的是类型模板参数,简单理解就是把类型当做参数传递给类/方法,今天我们第一个要介绍的就是与之对应的非类型模板参数
非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常
量来使用
比如说,我们想在c++中使用可以动态开辟大小的数组,就可以使用非类型模板参数
namespace zzzyh
{// 定义一个模板类型的静态数组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;};
}
如上我们就可以模拟实现一个动态开辟的数组
注意,浮点数、类对象以及字符串是不允许作为非类型模板参数的,要求在编译时期确认参数大小
模板特化
模板的作用是忽略类型上的不同,抽取共性,复用同一套逻辑,那么我们现在需要实现一个比较大小的模板,看看会不会有什么意想不到的问题
template<class T>
bool Less(T left, T right)
{return left < right;
}
看起来没什么问题,但是如果我们想比较两个地址里的值,用这种模板是有可能是不正确的
int main()
{int b = 20;int a = 10;int* t2 = &b;int* t1 = &a;cout<<Less(t1, t2);return 0;
}
原因很简单,这里比较的是两个地址的大小
此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方
式。模板特化中分为函数模板特化与类模板特化
函数模板特化
函数模板的特化步骤:
1. 必须要先有一个基础的函数模板
2. 关键字template后面接一对空的尖括号<>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇
怪的错误
template<>
bool Less<int*>(int* left, int* right)
{return *left < *right;
}
此时程序会自动调用特化之后的版本,而不走模板生成了
一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该
函数直接给出,不走模板特化的逻辑,比较推荐这种做法
类模板特化
全特化
全特化即是将模板参数列表中所有的参数都确定化
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;
}
偏特化
偏特化是与全特化相对的概念,其特点是特化部分参数,其中细分又可以分为指定具体的类型或者是像T*/T&这样的类型
部分特化
将模板参数类表中的一部分参数特化
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;
};
模板分离编译
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有
目标文件链接起来形成单一的可执行文件的过程称为分离编译模式
我们推荐将.cpp文件和.h文件分离开来,因为这会使工程项目一目了然
但是模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义,,在连接时会报错
为了解决这个问题,我们一般将声明和定义放到一个文件 "xxx.hpp" 里面或者xxx.h其实也是可以的。推荐使用这种。
当然也可以在模板定义的位置显式实例化,不常用这种方法
结语
以上便是今天的全部内容。如果有帮助到你,请给我一个免费的赞。
因为这对我很重要。
编程世界的小比特,希望与大家一起无限进步。
感谢阅读!
相关文章:
再谈c++模板
前言 在前面我们曾经简单的介绍过c的模板,但还并不全面,我们通过stl容器的学习加深了我们对c这门语言的理解。那么今天我们就再来谈一谈c模板,对模板再进行一点简单的补充 非类型模板参数 前面我们介绍的是类型模板参数,简单理…...
9.11 codeforces Div 2
文章目录 9.11 Div 2A. Doras Set(删除三个互质数)思路代码 B. Index and Maximum Value(范围加减1求max)思路代码 C. Dora and C(加a/b,最小化极差)思路代码 9.11 Div 2 Dashboard - Codeforces Round 969 (Div. 2) …...
二级菜单的两种思路(完成部分)
第一种 <el-form ref"formRef" :model"form" :rules"rules" label-width"120px"><el-form-item label"类型" prop"type"><el-select v-model"form.type" placeholder"请选择类型&q…...
【机器学习导引】ch2-模型评估与选择
文章目录 经验误差与过拟合 (Empirical error &overfitting)1. **均方误差(Mean Squared Error, MSE)**2. **均方根误差(Root Mean Squared Error, RMSE)**3. **平均绝对误差(Mean Absolute…...
二开ihoneyBakFileScan备份扫描
优点:可以扫描根据域名生成的扫描备份的扫描工具 二开部分:默认网址到字典(容易被封),二开字典到网址(类似test404备份扫描规则),同时把被封不能扫描的网址保存到waf_url.txt 中&am…...
leetcode21. 合并两个有序链表
思路: 用一个新链表来表示合并后的有序链表, 每次比较两个链表,将较小的那个结点存储至新链表中 # Definition for singly-linked list. # class ListNode(object): # def __init__(self, val0, nextNone): # self.val val # …...
搭建 WordPress 及常见问题与解决办法
浪浪云活动链接 :https://langlangy.cn/?i8afa52 文章目录 环境准备安装 LAMP 堆栈 (Linux, Apache, MySQL, PHP)配置 MySQL 数据库 安装 WordPress配置 WordPress常见问题及解决办法数据库连接错误白屏问题插件或主题冲突内存限制错误 本文旨在介绍如何在服务器上…...
《ORANGE‘s 一个操作系统的实现》--保护模式进阶
保护模式进阶 大内存读写 GDT段 ;GDT [SECTION .gdt] ; 段基址, 段界限 , 属性 LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符 LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ; Normal 描…...
【可变参模板】可变参类模板
可变参类模板也和可变参函数模板一样,允许模板定义含有0到多个(任意个)模板参数。可变参类模板参数包的展开方式有多种,以下介绍几种常见的方法。 一、递归继承展开 1.1类型模板参数包的展开 首先先看下面的代码: /…...
Linux 递归删除大量的文件
一般情况下 在 Ubuntu 中,递归删除大量文件和文件夹可以通过以下几种方式快速完成。常用的方法是使用 rm 命令,配合一些适当的选项来提高删除速度和效率。 1. 使用 rm 命令递归删除 最常见的方式是使用 rm 命令的递归选项 -r 来删除目录及其所有内容。…...
设计一个算法,找出由str1和str2所指向两个链表共同后缀的起始位置
假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,则可共享相同的后缀存储空间,例如,’loading’和’being’的存储映像如下图所示。 设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为 data…...
Python中如何判断一个变量是否为None
在Python中,判断一个变量是否为None是一个常见的需求,特别是在处理可选值、默认值或者是在函数返回结果可能不存在时。虽然这个操作本身相对简单,但围绕它的讨论可以扩展到Python的哲学、类型系统、以及如何在不同场景下优雅地处理None值。 …...
表观遗传系列1:DNA 甲基化以及组蛋白修饰
1. 表观遗传 表观遗传信息很多为化学修饰,包括 DNA 甲基化以及组蛋白修饰,即DNA或蛋白可以通过化学修饰添加附加信息。 DNA位于染色质(可视为微环境)中,并不是裸露的,因此DNA分子研究需要跟所处环境结合起…...
Android 跳转至各大应用商店应用详情页
测试通过机型品牌: 华为、小米、红米、OPPO、一加、Realme、VIVO、IQOO、荣耀、魅族、三星 import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import …...
Pywinauto鼠标操作指南
Pywinauto是一个强大的Python库,用于自动化Windows桌面应用程序的测试。它提供了一系列工具和API来模拟用户输入,包括键盘、鼠标事件,以及与各种窗口控件交互的能力。本文将详细介绍如何使用Pywinauto来执行鼠标操作,并通过一些示…...
VRAY云渲染动画怎么都是图片?
动画实际上是由一系列连续的静态图像(帧)组成的,当这些帧快速连续播放时,就形成了动画效果。每一帧都是一个单独的图片,需要单独渲染。 云渲染农场的工作方式: 1、用户将3D场景文件和动画设置上传到云渲染…...
共享内存(C语言)
目录 一、引言 二、共享内存概述 1.什么是共享内存 2.共享内存的优势 三、共享内存的实现 1.创建共享内存 2.关联共享内存 3.访问共享内存 4.解除共享内存关联 5.删除共享内存 四、共享内存应用实例 五、总结 本文将深入探讨C语言中的共享内存技术,介绍其原理、…...
《JavaEE进阶》----16.<Mybatis简介、操作步骤、相关配置>
本篇博客讲记录: 1.回顾MySQL的JDBC操作 2..Mybatis简介、Mybatis操作数据库的步骤 3.Mybatis 相关日志的配置(日志的配置、驼峰自动转换的配置) 前言 之前学习应用分层时我们知道Web应用程序一般分为三层,Controller、Service、D…...
HuggingFists算子能力扩展-PythonScript
HuggingFists作为一个低代码平台,很多朋友会关心如何扩展平台算子能力。扩展平台尚不支持的算子功能。本文就介绍一种通过脚本算子扩展算子能力的解决方案。 HuggingFists支持Python和Javascript两种脚语言的算子。两种语言的使用方式相同,使用者可以任选…...
WInform记录的添加和显示
1、程序 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace ComboBoxApp {public part…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
spring boot使用HttpServletResponse实现sse后端流式输出消息
1.以前只是看过SSE的相关文章,没有具体实践,这次接入AI大模型使用到了流式输出,涉及到给前端流式返回,所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...
机器学习复习3--模型评估
误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异称为:误差(error)。 误差定义: ①在训练集上的误差称为训练误差(training error)或经验误差(empirical error&#x…...
VUE3 ref 和 useTemplateRef
使用ref来绑定和获取 页面 <headerNav ref"headerNavRef"></headerNav><div click"showRef" ref"buttonRef">refbutton</div>使用ref方法const后面的命名需要跟页面的ref值一样 const buttonRef ref(buttonRef) cons…...
ABB馈线保护 REJ601 BD446NN1XG
配电网基本量程数字继电器 REJ601是一种专用馈线保护继电器,用于保护一次和二次配电网络中的公用事业和工业电力系统。该继电器在一个单元中提供了保护和监控功能的优化组合,具有同类产品中最佳的性能和可用性。 REJ601是一种专用馈线保护继电器…...
