当前位置: 首页 > news >正文

模板的进阶

目录

非类型模板参数

C++11的静态数组容器-array 

按需实例化

模板的特化

函数模板特化

类模板特化

全特化与偏特化

模板的分离编译

总结


非类型模板参数

基本概念:模板参数类型分为类类型模板参数和非类类型模板参数

  • 类类型模板参数:跟在class 或 typename之后的形参
  • 非类类类型模板参数:用一个常量作为类模板的参数

功能:编译时合理分配大小

#include <iostream>
using namespace std;namespace bit
{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;};
}int main()
{bit::array<int> a1;bit::array<int, 10> a2;bit::array<int, 100> a3;return 0;
}

注意事项: 

1、浮点数、类类型的对象及字符串不允许作为非类类型模板参数

2、非类类型模板参数是在编译时传参,函数参数是在运行时传参

3、函数参数(T 对象1,T 对象2)| 模板参数<class 类型1,class 类型2>

C++11的静态数组容器-array 

array文档:<array> - C++ Reference (cplusplus.com)

#include <iostream>
#include <assert.h>
#include <array>
using namespace std;int main()
{std::array<int, 10> a1;int a2[10];//越界读,检查不出来a2[10];//越界写,抽查,局限多,很多位置查不出来(x86环境下运行a2[15]不报错,a[10] = 1报错)a2[15] = 1;//任意读写越界都能检查出来a1[10];//报错return 0;
}

优点: 可以避免数组越界问题(但实际上这些内容vector就可以做到,array没啥用)

std::vector<int> v1(10,0); 
v1[10]//v1[10]也可以检测出

缺点:会出现栈溢出问题

std::array<int,1000000> a3;//报错
std::vector<int> v2(1000000,0);//正确

按需实例化

include <iostream>
#include <array>
#include <vector>
#include <assert.h>
using namespace std;namespace bit
{template<class T, size_t N = 10>class array{public:T& operator[](size_t index){assert(index < N);size(1);//语法错误,但是不报错return _array[index];}const T& operator[](size_t index)const{assert(index < N);return _array[index];}size_t size()const{return _size;}bool empty()const{return 0 == _size;}private:T _array[N];size_t _size;};
}int main()
{bit::array<int> a1;cout<<a1.empty()<<endl;//不报错a1[1];//增加一个调用a1[1]时报错return 0;
}

运行上述代码后不会报错,即使size(1)是一个语法错误(size函数不需要传参)是因为

  1. 在编译器遇到模板时,预处理阶段后不会直接编译,而是根据模板的“蓝图” + 传入模板的参数类型等内容,将模板进行实例化后才会进行编译阶段(调试时是已经经历了四个阶段的)
  2. 在实例化类模板时会进行按需实例化,即调用哪个成员函数就实例化哪个(调用empty就仅实例化该函数)

没有报错的本质就是没有调用operator[],所以operator[]中的错误不会被检查出来,只有调用才会细致检查语法错误

  • 当然编译器还是会大体框架进行检查,比如少了}多个}之类的错误

模板的特化

基本概念:在原模板类的基础上,针对特殊类型所进行特殊化处理

        通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到

一些错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板:

#include <iostream>
using namespace std;class Date
{
public:friend ostream& operator<<(ostream& _cout, const Date& d);Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}// 函数模板 -- 参数匹配
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, 6);cout << Less(d1, d2) << endl; // 可以比较,结果正确(会调用日期类对象的<重载)Date* p1 = &d1;Date* p2 = &d2;//(传入日期类对象的指针进行比较)cout << Less(p1, p2) << endl; // 可以比较,结果错误return 0;
}

        p1指向的d1显然大于p2指向的d2对象,但是Less内部并没有比较p1和p2指向的对象内容,

而比较的是p1和p2指针的地址,因而无法达到预期而错误

函数模板特化

注意事项:

  • 1、必须要现有一个基础的函数模板
  • 2、template后接一个空的尖括号<>
  • 3、函数名后跟一对尖括号,尖括号中指定需要特化的类型
  • 4、函数形参顺序必须要和模板函数的基础参数类型完全相同,若不同则编译器可能报错
#include <iostream>
using namespace std;class Date
{
public:friend ostream& operator<<(ostream& _cout, const Date& d);Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}//函数模板
template<class T>
bool Less(T left, T right)
{cout << "bool Less(T left, T right)" << endl;return left < right;
}特化(但是该特化还是会出错)
//template<>
//bool Less(Date* left, Date* right)
//{
//	cout << "bool Less(T* left, T* right)" << endl;
//	return *left < *right;
//}//不会出错但是不符合特化定义
template<class T>
bool Less(T* left, T* right)
{cout << "bool Less(T* left, T* right)" << endl;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 = new Date(2022, 7, 7);Date* p2 = new Date(2022, 7, 8);cout << Less(p1, p2) << endl; // 可以比较,结果错误int* p3 = new int(3);int* p4 = new int(4);cout << Less(p3, p4) << endl; //可以比较,结果错误return 0;
}

~~依然是哪个类型更匹配就用哪个 ~~

结论:函数模板不建议特化do且函数模板特化的使用场景少

类模板特化

全特化与偏特化

全特化:将模板参数列表中的所有参数都确定化

偏/半特化:将模板参数列表中的部分参数确定化

  • 偏特化又分为:“部分特化” 和“参数更进一步的限制”
#include <iostream>
using namespace std;//Data类模板
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;}
};//偏/半特化(部分特化)
template<class T1>
class Data<T1, char>
{
public:Data(){cout << "Data <T1,char>" << endl;}
};//偏/半特化(对参数进一步限制)
template<class T1,class T2>
class Data<T1*, T2*>
{
public:Data(){cout << "Data <T1*,T2*>" << endl;}
};//偏/半特化(对参数进一步限制)
template<class T1, class T2>
class Data<T1&, T2*>
{
public:Data(){cout << "Data <T1&,T2*>" << endl;}
};int main()
{Data<int, int> d1;Data<int, char> d2;Data<char, char> d3;Data<char*, char*> d4;Data<int*, char*> d5;Data<int*, string*> d6;Data<int&, string*> d7;return 0;
}

匹配机制:有现成的就用现成的,没有现成的就用那个最合适的

注意事项:如果传入的是Data*,特化时的T*就会变成Date*而不是Data**,T*是一个整体

模板的分离编译

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

假如有以下场景,模板声明和定义分离,在头文件中进行声明,在源文件中进行定义:

//a.h文件
tempate<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;
}

 22、2:33处

注意事项:模板的声明和定义支持分离,但不支持分离在两个文件(STL库中的模板的定义和分离都是在.h文件中的)

总结

优点:

  1. 复用了代码,节省资源,更快的迭代开发,C++的标准模板库也因此而生
  2. 增强代码灵活性

缺点:

  1. 模板会导致代码膨胀问题,也会导致编译时间变长
  2. 出现模板编译错误时,错误信息十分混乱,不易定位

~over~

相关文章:

模板的进阶

目录 非类型模板参数 C11的静态数组容器-array 按需实例化 模板的特化 函数模板特化 类模板特化 全特化与偏特化 模板的分离编译 总结 非类型模板参数 基本概念&#xff1a;模板参数类型分为类类型模板参数和非类类型模板参数 类类型模板参数&#xff1a;跟在class…...

微服务中Dubbo通俗易懂讲解及代码实现

当你在微服务架构中需要不同服务之间进行远程通信时&#xff0c;Dubbo是一个优秀的选择。Dubbo是一个高性能的Java RPC框架&#xff0c;它提供了服务注册、发现、调用、负载均衡等功能&#xff0c;使得微服务之间的通信变得简单而高效。 让我们来看一下Dubbo的通俗易懂的解释和…...

Unity HDRP Release-Notes

&#x1f308;HDRP Release-Notes 收集的最近几年 Unity各个版本中 HDRP的更新内容 信息收集来自自动搜集工具&#x1f448; &#x1f4a1;HDRP Release-Notes 2023 &#x1f4a1;HDRP Release-Notes 2022 &#x1f4a1;HDRP Release-Notes 2021...

Chrome将网页保存为PDF的实战教程

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

zotero7+Chat GPT实现ai自动阅读论文

关于这一部分的内容我在哔哩哔哩上发布了视频教程 视频链接见&#xff1a; zotero7GPT AI快速阅读文献_哔哩哔哩_bilibili 相关下载的官方链接如下&#xff1a; 1、zotero7 测试版官方下载链接&#xff1a; https://www.zotero.org/support/beta_builds 2、 InfiniCLOUD 云…...

STM32外设配置以及一些小bug总结

USART RX的DMA配置 这里以UART串口1为例&#xff0c;首先点ADD添加RX和TX配置DMA&#xff0c;然后模式一般会选择是normal&#xff0c;这个模式是当DMA的计数器减到0的时候就不做任何动作了&#xff0c;还有一种循环模式&#xff0c;是计数器减到0之后&#xff0c;计数器自动重…...

【数据结构与算法】:10道链表经典OJ

目录 1. 移除链表元素2. 反转链表2.1反转指针法2.2 头插法 3. 合并两个有序链表4. 分隔链表5. 环形链表6. 链表的中间节点7. 链表中倒数第K个节点8. 相交链表9. 环形链表的约瑟夫问题10. 链表的回文结构 1. 移除链表元素 思路1&#xff1a;遍历原链表&#xff0c;将 val 所在的…...

Python SQL解析和转换库之sqlglot使用详解

概要 Python SQLGlot是一个基于Python的SQL解析和转换库,可以帮助开发者更加灵活地处理和操作SQL语句。本文将介绍SQLGlot库的安装、特性、基本功能、高级功能、实际应用场景等方面。 安装 安装SQLGlot库非常简单,可以使用pip命令进行安装: pip install sqlglot安装完成后…...

NULL—0—nullptr 三者关系

1.概述 NULL&#xff0c;0&#xff0c;nullptr值都是0&#xff0c;但是类型不同&#xff0c;但是由于C头文件中NULL定义宏混乱&#xff0c;可能是int 0&#xff0c;也可能是(void*)0; 所以在C11及以后的标准中引入新的空指针nullptr&#xff0c;nullptr就是(void*)0&#xff…...

Nginx 请求的 匹配规则 与 转发规则

博文目录 文章目录 URL 与 URI匹配规则案例说明 转发规则响应静态资源案例说明 转发动态代理案例说明案例说明 URL 与 URI 通常, 一个 URL 由以下部分组成 scheme://host:port/path?query#fragment scheme: 协议, 如 http, https, ftp 等host; 主机名或 IP 地址post: 端口…...

OWASP发布10大开源软件风险清单

3月20日&#xff0c;xz-utils 项目被爆植入后门震惊了整个开源社区&#xff0c;2021 年 Apache Log4j 漏洞事件依旧历历在目。倘若该后门未被及时发现&#xff0c;那么将很有可能成为影响最大的软件供应链漏洞之一。近几年爆发的一系列供应链漏洞和风险&#xff0c;使得“加强开…...

大学生前端学习第一天:了解前端

引言&#xff1a; 哈喽&#xff0c;各位大学生们&#xff0c;大家好呀&#xff0c;在本篇博客&#xff0c;我们将引入一个新的板块学习&#xff0c;那就是前端&#xff0c;关于前端&#xff0c;GPT是这样描述的&#xff1a;前端通常指的是Web开发中用户界面的部分&#xff0c;…...

公安机关人民警察证照片采集规范及自拍制作电子版指南

在当今社会&#xff0c;证件照的拍摄已成为我们生活中不可或缺的一部分。无论是办理身份证、驾驶证还是护照&#xff0c;一张规范的证件照都是必需的。而对于公安机关的人民警察来说&#xff0c;证件照片的采集更是有着严格的规范和要求。本文将为您详细介绍公安机关人民警察证…...

使用Python插入100万条数据到MySQL数据库并将数据逐步写出到多个Excel

Python插入100万条数据到MySQL数据库 步骤一&#xff1a;导入所需模块和库 首先&#xff0c;我们需要导入 MySQL 连接器模块和 Faker 模块。MySQL 连接器模块用于连接到 MySQL 数据库&#xff0c;而 Faker 模块用于生成虚假数据。 import mysql.connector # 导入 MySQL 连接…...

【备忘录】openssl记录

openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -days 10000 -out ca.crt -subj “/CCN/STBeijing/LBeijing/Okubernetes/OUKubernetes-manual/CNkubernetes-ca” openssl genrsa -out etcd-ca.key 2048 openssl req -x509 -new -nodes -key etc…...

hadoop编程之工资序列化排序

数据集展示 7369SMITHCLERK79021980/12/17800207499ALLENSALESMAN76981981/2/201600300307521WARDSALESMAN76981981/2/221250500307566JONESMANAGER78391981/4/22975207654MARTINSALESMAN76981981/9/2812501400307698BLAKEMANAGER78391981/5/12850307782CLARKMANAGER78391981/…...

OpenXR手部跟踪接口与VIVE OpenXR扩展详细解析

随着虚拟现实技术的发展&#xff0c;手部跟踪已成为提高沉浸感和交互性的关键技术。OpenXR标准为开发者提供了一套手部跟踪的扩展接口&#xff0c;特别是针对VIVE设备的特定实现。以下是这些接口和类的详细解释&#xff1a; 1. VIVE.OpenXR.Hand VIVE.OpenXR.Hand 是HTC VIVE…...

慎投!5本On Hold全被剔除!新增9本SCI/SSCI被除名!4月WOS更新

本周投稿推荐 SSCI • 2/4区经管类&#xff0c;2.5-3.0&#xff08;录用率99%&#xff09; SCIE&#xff08;CCF推荐&#xff09; • 计算机类&#xff0c;2.0-3.0&#xff08;最快18天录用&#xff09; SCIE&#xff08;CCF-C类&#xff09; • IEEE旗下&#xff0c;1/2…...

华为云CodeArts IDE For Python 快速使用指南

CodeArts IDE 带有 Python 扩展&#xff0c;为 Python 语言提供了广泛的支持。Python 扩展可以利用 CodeArts IDE 的代码补全、验证、调试和单元测试等特性&#xff0c;与多种 Python 解释器协同工作&#xff0c;轻松切换包括虚拟环境和 conda 环境的 Python 环境。本文简要概述…...

C# 截图并保存为图片

在winform开发中&#xff0c;有时会用到截图并保存为图片的时候&#xff0c;这里列了三种保存图片的可能情况。 将窗体截图保存成图片的方式是&#xff1a; Bitmap bit new Bitmap(this.Width, this.Height);//实例化一个和窗体一样大的bitmap Graphics g Graphics.FromImag…...

[html]一个动态js倒计时小组件

先看效果 代码 <style>.alert-sec-circle {stroke-dasharray: 735;transition: stroke-dashoffset 1s linear;} </style><div style"width: 110px; height: 110px; float: left;"><svg style"width:110px;height:110px;"><cir…...

Hive-Sql复杂面试题

参考链接&#xff1a;hive sql面试题及答案 - 知乎 有哪些好的题目都可以给我哦 我来汇总到一起 1、编写sql实现每个用户截止到每月为止的最大单月访问次数和累计到该月的总访问次数 数据&#xff1a; userid,month,visits A,2015-01,5 A,2015-01,15 B,2015-01,5 A,2015-01,…...

WPS二次开发系列:WPS SDk功能就概览

作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 作者通过深度测试使用了WPS SDK提供的Demo&#xff0…...

华为OD-C卷-结队编程[200分]

题目描述 某部门计划通过结队编程来进行项目开发, 已知该部门有 N 名员工,每个员工有独一无二的职级,每三个员工形成一个小组进行结队编程, 结队分组规则如下: 从部门中选出序号分别为 i、j、k 的3名员工,他们的职级分别为 level[i],level[j],level[k], 结队小组满…...

连连看游戏页面网站源码,直接使用

可以上传自己喜欢的图片 游戏页面 通关页面 源码免费下载地址抄笔记 (chaobiji.cn)...

在 Kubernetes 1.24 中使用 Docker:配置与应用指南

在 Kubernetes 1.24 中使用 Docker&#xff1a;配置与应用指南 引言 随着 Kubernetes 社区对容器运行时接口&#xff08;CRI&#xff09;的标准化推进&#xff0c;Docker 原生支持在 Kubernetes 1.24 版本中被弃用。然而&#xff0c;许多开发者和组织仍希望继续使用 Docker。…...

Canvas使用详细教学:从基础绘图到进阶动画再到实战(海报生成、Flappy Bird 小游戏等),掌握绘图与动画的秘诀

一、Canvas基础 1. Canvas简介 Canvas是HTML5引入的一种基于矢量图形的绘图技术&#xff0c;它是一个嵌入HTML文档中的矩形区域&#xff0c;允许开发者使用JavaScript直接操作其内容进行图形绘制。Canvas元素不包含任何内在的绘图能力&#xff0c;而是提供了一个空白的画布&a…...

【MATLAB 分类算法教程】_2粒子群算法优化支持向量机SVM分类 - 教程和对应MATLAB代码

分类代码案例2:粒子群算法优化支持向量机SVM分类 - MATLAB完全代码教程 1. 初始化代码2. 读取数据代码3.数据预处理代码4.利用粒子群算法PSO求解最佳的SVM参数c和g代码5.根据最佳的参数进行SVM模型训练代码6.SVM模型预测代码7.准确率分析以及分类结果对比作图代码本文以红酒数…...

Vue2电商前台项目(三):完成Search搜索模块业务

目录 一、请求数据并展示 1.写Search模块的接口 2.写Vuex中的search仓库&#xff08;三连环&#xff09; 3.组件拿到search仓库的数据 用getters简化仓库中的数据 4.渲染商品数据到页面 5.search模块根据不同的参数获取数据展示 &#xff08;1&#xff09;把派发action…...

算法思想总结:链表

一、链表的常见技巧总结 二、两数相加 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {//利用t来存进位信息int t0;ListNode*newheadnew ListNode(0);//创建一个哨兵节点&#xff0c;方便尾插List…...

提供微商城网站建设/北京网站seo服务

文章目录创建私钥创建CSR批准证书签名请求获取证书绑定角色添加到kubeconfig创建私钥 openssl genrsa -out kevin.key 2048 openssl req -new -key kevin.key -out kevin.csr创建CSR cat <<EOF | kubectl apply -f - apiVersion: certificates.k8s.io/v1beta1 kind: Ce…...

基于liferay portal的乡镇企业门户网站建设研究/关键词数据

一. System: 首先是System类&#xff0c;因为从一开始从接触java起&#xff0c;我们就无时无刻都在接触它&#xff0c;经常用它来向屏幕&#xff0c;向控制台打印输出一些信息&#xff0c;System.out.println(“hello world”);这个只是在控制台输出一条信息“hello world”&am…...

真正免费建站的网站/百度sem是什么

背景 运行脚本出现 SWT folder ..\lib\location of your Java installation. does not exist. Please set ANDROID_SWT to point to the folder containing swt.jar for your platform. 比如&#xff1a; 解决方案 基本上是JDK没装正确版本或者环境变量配置混乱&#xff0c;标准…...

极度简单wordpress主题/快速优化系统

用CDN的七个理由 浏览器从服务器上下载css、js和图片等文件时都要和服务器连接&#xff0c;而大部分浏览器对同一个域名用于下载文件的并发连接数限制在4个&#xff0c;这意味着如果要下载第五个文件就必须等前四个文件中有一个已经加载完成&#xff0c;假如前4个文件都很大&am…...

北京装饰网站建设/网络营销策略的定义

CentOS 5.5的内核版本是2.6.18-194.e15 GCC版本是4.1.2 (20080704) CentOS 5.5自带的boost 1.33&#xff0c;这个版本比较老了&#xff0c;几年前的版本。主要是&#xff0c;这个版本没有ASIO。所以决定重新编译一个boost。 首先去http://www.boost.org/下载一个最新的boost 1.…...

查网站是什么公司做的/百度上海分公司地址

主要内容&#xff1a;使用JDBC访问数据库中数据&#xff08;Java Web数据可视化案例&#xff09; 文章目录前期准备&#xff1a;案例&#xff1a;第一步&#xff1a;创建数据库及数据第二步&#xff1a;编写实体类第三步&#xff1a;编写Dao类第四步&#xff1a;编写Servlet代码…...