【C++进阶(七)】仿函数深度剖析模板进阶讲解
💓博主CSDN主页:杭电码农-NEO💓
⏩专栏分类:C++从入门到精通⏪
🚚代码仓库:NEO的学习日记🚚
🌹关注我🫵带你学习C++
🔝🔝

模板进阶
- 1. 前言
- 2. 仿函数的概念
- 3. 仿函数的实际用途
- 4. 模板的非类型模板参数
- 5. 模板的特化简单介绍
- 6. 函数模板深度剖析
- 7. 类模板的特化深度剖析
- 7.1 模板的全特化
- 7.2 模板的偏特化
- 8. 总结以及拓展
1. 前言
C++进阶中关于STL库的初级数据
结构就已经结束了,高阶数据结构如:
二叉搜索树AVL树,红黑树,哈希
等等将在C++高阶讲解.
本章重点:
本篇文章着重讲解仿函数的概念
以及自行实现一个仿函数.模板进阶
中,着重讲解非类型模板参数,模板
的特化还有模板的分离编译
2. 仿函数的概念
仿函数的本质就是一个类,此类中
运算符重载了括号()!所以它使用起来
和函数很相似,就叫做仿函数
在标准库的优先级队列的类模板中
有这样一个缺省参数叫less:

这个less就是一个仿函数,它会将
优先级队列变成大堆,在算法库的
sort函数默认是升序,其实就是用的less
与less对应的仿函数是greater,greater
可以将优先级队列变成小堆,将sort变成降序
我们可以模仿实现一下less的使用场景:
class Less
{
public:bool operator()(int x,int y){return x<y;}
};
int main()
{Less functor;cout<<functor(1,2);
}
注:1小于2,会返回true,打印1
3. 仿函数的实际用途
首先是使用库中的某些函数时
仿函数能很方便的改变升降序或大小堆
升序写法:
vector<int> v{9,8,7,6};
sort(v.begin(),v.end());
sort(v.begin(),v.end(),less<int>);
降序写法:
vector<int> v{6,7,8,9};
sort(v.begin(),v.end(),greater<int>);
大堆写法:
priority_queue<int> p1;
priority_queue<int,vector<int>,less<int>> p2;
小堆写法:
priority_queue<int,vector<int>,greater<int>> p;
注:优先级队列的适配器参数在仿函数
前面,想要显示传仿函数,先要穿前面的
当然,greater的内部实现和less
只差了一个符号而已,如下:
class Greater
{
public:bool operator()(int x,int y){return x>y;}
};
4. 模板的非类型模板参数
模板参数类型解析:
模板参数分类类型形参与非类型形参
类型形参即:出现在模板参数列表中
跟在class/typename之后的参数类型
非类型形参,就是用一个常量作为
类(函数)模板的一个参数,在类(函数)
模板中可将该参数当成常量来使用
比如:
template<class T,int N = 10>
class test
{T a[N];
};test<int,50> t1;
test<double> t2;
注:N=10是缺省值,没传时默认为10

讲到这儿就不得不介绍STL中一个不常用的容器了

array是静态数组
也就是固定大小的顺序容器
使用时,要显示传参N来初始化数组
array属于C++的数组,使用array
时,不管是越界读还是越界写都能
被检测到从而报错,然而使用C语言
的数组时,越界读写不一定会报错
5. 模板的特化简单介绍
通常情况下,使用模板可以实现一些与
类型无关的代码,但对于一些特殊类型的
可能会得到一些错误的结果需要特殊处理
比如:实现用来进行小于比较的函数模板
template<class T>
bool Less(T left, T right)
{return left < right;
}
Less绝对多数情况下都可以正常比较
但是在特殊场景下就得到错误的结果
比如这里我传入指针地址过来
这里的比较就会有问题,我想比较
的是指针指向的内容,然而传入指针
的话会比较指针的地址高低,就和数据无关
此时,就需要对模板进行特化
即:在原模板类的基础上
针对特殊类型所进行特殊化的实现方式
类模板分为函数模板和类模板
6. 函数模板深度剖析
函数模板的特化步骤:
- 必须要先有一个基础的函数模板
- 关键字template后面接一对空的尖括号<>
- 函数名后跟一对尖括号,尖括号中指定需要特化的类型
- 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误
// 函数模板 -- 参数匹配
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类型的指针
那么就不会调用第一个函数,而是走
第二个特化的函数,特化也就是特殊处理
注:一般情况下如果函数模板遇到不能处理或者处理有误的类型
为了实现简单通常都是将该函数直接给出
bool Less(int* left, int* right)
{return *left < *right;
}
所以实际上函数模板的特化是不常用的
7. 类模板的特化深度剖析
类模板的特化分为全特化和偏特化
7.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;
};
Data<int, int> d1;
Data<int, char> d2;
和函数模板特化一样,特化的部分
要加上template<>作为格式,上面
初始化时,<int,int>类型不会走模板特化
然而<int,char>类型会走模板特化
7.2 模板的偏特化
偏特化:
任何针对模版参数进一步进行条件限制设计的特化版本
然而偏特化又有两种表现形式:
- 部分特化
- 对参数做进一步限制
比如对于上面例子中的模板类做部分特化:
// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:Data() {cout<<"Data<T1, int>" <<endl;}
private:T1 _d1;int _d2;
};
此时,只要第二个参数是int,就会
走偏特化,第二个参数不是int就不走
对上面的类做参数进一步限制:
//两个参数偏特化为指针类型
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; };
8. 总结以及拓展
补充完仿函数和模板进阶相关知识后
接下来我们将进入继承和多态的学习
继承和多态这部分在校招中考察的很多
请耐心学习~~
对于模板分离编译的拓展:
为什么模板不能分离编译?
模板分离编译问题剖析
相关文章:
【C++进阶(七)】仿函数深度剖析模板进阶讲解
💓博主CSDN主页:杭电码农-NEO💓 ⏩专栏分类:C从入门到精通⏪ 🚚代码仓库:NEO的学习日记🚚 🌹关注我🫵带你学习C 🔝🔝 模板进阶 1. 前言2. 仿函数的概念3. 仿函数的实…...
基于SSM的电动车上牌管理系统(有报告)。Javaee项目。
演示视频: 基于SSM的电动车上牌管理系统(有报告)。Javaee项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring SpringM…...
mstsc无法保存RDP凭据, 100%生效
问题 即使如下两项都打勾,其还是无法保存凭据,特别是连接Ubuntu (freerdp server): 解决方法 网上多种复杂方法,不生效,其思路是修改后台配置,以使mstsc跟平常一样自动记住凭据。最后,如下的…...
OpenGLES:绘制一个混色旋转的3D球体
效果展示 本篇博文会实现一个混色旋转的3D球体 一.球体解析 前面几篇博文讲解了如何使用OpenGLES实现不同的3D图形 本篇博文讲解怎样实现3D世界的代表图形:一个混色旋转的3D球体 1.1 极限正多面体 如果有学习过我前几篇3D图形绘制的博文,就知道要想…...
Spring AOP 基于注解源码整理
导入配置类 EnableAspectJAutoProxy 注解导入 AspectJAutoProxyRegistrarImportBeanDefinitionRegistrar#registerBeanDefinitions向容器中加入AnnotationAwareAspectJAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator#initBeanFactory初始化ReflectiveAspectJAdvisor…...
C语言 —— 函数栈帧的创建和销毁
在我们之前学习函数的时候,我们可能有很多困惑? 比如: 局部变量是怎么创建的?为什么局部变量的值是随机值?函数是怎么传参的?传参的顺序是怎样的?形参和实参是什么关系?函数调用是怎么做的?函数调用是结束后怎么返回的? 那么要解决这些问题, 我们就需要知道…...
Appleid苹果账号自动解锁改密(自动解锁二验改密码)
目前该项目能实现以下功能: 多用户使用,权限控制多账号管理账号分享页,支持设置密码、有效期、自定义HTML内容自动解锁与关闭二步验证自动/定时修改密码自动删除Apple ID中的设备代理池与Selenium集群,提高解锁成功率允许手动触发…...
Conflicting peer dependency: eslint@8.50.0
npm install 输出 npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: vue/eslint-config-standard6.1.0 npm ERR! Found: eslint-plugin-vue8.7.1 npm ERR! node_modules/eslint-plugin-vue npm ERR! dev eslint-plugin-vue…...
Vue3 defineProps使用
MyTag.vue <script setup> import { ref, nextTick, defineProps, defineEmits } from "vue"; const props defineProps({flag: Boolean,title: String, }); // 写成这样也可以 // const props defineProps(["flag", "title"]);const e…...
机器学习7:逻辑回归
一、说明 逻辑回归模型是处理分类问题的最常见机器学习模型之一。二项式逻辑回归只是逻辑回归模型的一种类型。它指的是两个变量的分类,其中概率用于确定二元结果,因此“二项式”中的“bi”。结果为真或假 — 0 或 1。 二项式逻辑回归的一个例子是预测人…...
生活小记-纸张尺寸
A系列纸张: A0:841 x 1189 毫米A1:594 x 841 毫米A2:420 x 594 毫米A3:297 x 420 毫米A4:210 x 297 毫米A5:148 x 210 毫米A6:105 x 148 毫米A7:74 x 105 毫米A8…...
【MATLAB源码-第41期】基于压缩感知算法的OFDM系统信道估计和LS算法对比仿真。
操作环境: MATLAB 2013b 1、算法描述 压缩感知(Compressed Sensing, CS)是一种从稀疏或可压缩信号中重构完整信号的数学理论和技术。下面详细介绍压缩感知和它在OFDM信道估计中的应用。 1. 压缩感知基本概念 在传统采样理论中࿰…...
优思学院|六西格玛将烹饪和美味提升至极致
最近,我们曾提到一个美国男子如何利用六西格玛来控制糖尿病。这表明六西格玛逐渐被认为是一个不仅可以在工作场所之外使用,尤其不仅限于制造业的系统。 六西格玛的核心理念是改进过程的质量,从而改善最终结果。如果你做了晚餐或尝试了一道新…...
git stash
git stash 是 Git 中一个非常有用的命令,用于临时保存当前工作目录中的修改,以便你可以切换到其他分支或处理其他任务而不丢失你的修改。它的主要用途是: 保存未提交的修改:你可以使用 git stash 命令将未提交的修改(包…...
Flink Data Source
Flink Data Source 一、内置 Data Source Flink Data Source 用于定义 Flink 程序的数据来源,Flink 官方提供了多种数据获取方法,用于帮助开发者简单快速地构建输入流,具体如下: 1.1 基于文件构建 1. readTextFile(path):按照 TextInputFormat 格式读取文本文件,并将…...
怒刷LeetCode的第23天(Java版)
目录 第一题 题目来源 题目内容 解决方法 方法一:贪心算法 方法二:动态规划 方法三:回溯算法 方法四:并查集 第二题 题目来源 题目内容 解决方法 方法一:排序和遍历 方法二:扫描线算法 方法…...
Golang 中的调试技巧
掌握有效的策略和工具,实现顺畅的开发 调试是每位开发人员都必须掌握的关键技能。它是识别、隔离和解决代码库中问题的过程。在 Golang 的世界中,掌握有效的调试技巧可以显著提升您的开发工作流程,并帮助您创建更可靠和健壮的应用程序。在本…...
linux 监控内存利用率
监控内存利用率 使用free来分析CPU使用信息 #!/bin/bashDATE$(date %F" "%H:%M)IP$(ifconfig eth0 |awk -F [ :] /inet addr/{print $4}) MAIL"examplemail.com"TOTAL$(free -m |awk /Mem/{print $2})USE$(free -m |awk /Mem/{print $3-$6-$7})FREE$(($TO…...
43 验证二叉搜索树
验证二叉搜索树 理解题意:验证搜索二叉树:中序遍历是升序题解1 递归(学习学习!)题解2 中序遍历(保持升序) 给你一个二叉树的根节点 root ,判断其是否是一个 有效的二叉搜索树。 有…...
深度学习笔记之微积分及绘图
深度学习笔记之微积分及绘图 学习资料来源:微积分 %matplotlib inline from matplotlib_inline import backend_inline from mxnet import np, npx from d2l import mxnet as d2lnpx.set_np()def f(x):return 3 * x ** 2 - 4 * xdef numerical_lim(f, x, h):retur…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
