C++之模板进阶(探索C++模板:非类型参数与特化技巧)
本节目标:
1.非类型模板参数
2.类模板的特化
3.类模板特化的应用之类型萃取
4.模板的分离编译
非类型模板参数
模板参数分 类型形参与非类型形参
类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称
非类型形参:就是用一个常量作为类(函数)模板的一个参数,可将参数当成常量来使用
比如
template<class T>
class A
{bool operator()(const T&x)
{}}
这种是类型模板参数,因为你创建A的时候要指明类型,比如 A<int> a; int就是一个类型
那什么叫非类型模板参数???
template<int N>
这种就是非类型模板参数,直接定义了一个N,作用就类似#define N 100;
这样你传参就可以 A<100> a; // 这个100就会传给N
非类型模板参数的作用(解决什么应用场景)
此时我的数组长度已经固定为100,那如果我想弄一个200的呢???
就是我封装了一个静态数组,无非改变其容量
那非类型模板参数就可以解决这类问题
注意事项:
1.注意这个N是不能修改的,是一个常量
2..浮点数,类对象以及字符串是不允许作为非类型模板参数的
3.非类型的模板参数必须在编译期就能确定结果
class MyClass { /* ... */ };MyClass obj; // 运行时创建的对象template <MyClass obj> // 错误!无法在编译时确定obj的值
class A { /* ... */ };
字符串常量是一个指针,指针指向的物理地址是会变的
浮点数主要与精度有问题,每个编译器处理不一样
模板的特化
什么叫模板的特化???
模板的特化就是模板的特殊化,通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,也就是你想针对这个类型的模板特殊化处理得到一些特殊的结果
// 通用模板
template <typename T>
struct Comparator {bool operator()(const T& a, const T& b) const {return a == b; // 默认使用 ==运算符}
};// 特化版本:针对 const char*(C风格字符串)
template <>
struct Comparator<const char*> {bool operator()(const char* a, const char* b) const {return std::strcmp(a, b) == 0; // 使用strcmp进行字符串比较}
};
如果没有特化版本
那我们在调用Comparator("hello","world")去比较两个字符串的大小的时候
就会直接调通用版本,你本质是想比较hello和world,但你传的是一个字符串常量
也就是你的类型是const char*,指针,比较的是指针,这与你原来的意思相背
所以此时就需要模板的特化
针对某些类型的特殊化处理,与正常模板处理不一样
模板的特化分为函数模板特化和类模板特化
函数的模板特化:
1.必须要先有一个基础的函数模板
2.关键字template后面接一对空的尖括号<>
3.函数名后跟一对尖括号,尖括号中指定需要特化的类型
4.函数形参表:必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的 错误
// 通用模板
template <typename T>
ReturnType functionName(T param) {// 通用实现
}// 全特化版本(针对特定类型)
template <>
ReturnType functionName<SpecificType>(SpecificType param) {// 特化实现
}
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出 (就是你直接自己实现一个就行了,不要去想什么特不特化)
总结:模板特化必须遵循 “先通用,后特化” 的顺序。这是 C++ 模板系统的设计原则,确保类型安全和编译期的正确匹配。如果需要为特定类型提供完全不同的实现,且不想依赖通用模板,建议使用函数重载或独立类替代特化。
类模板的特化
对于类模板的特化 :分为全特化和偏特化
全特化:将模板参数列表中所有的参数都确定化
偏特化:任何针对模板参数进一步进行条件限制设计的特化版本
// 通用模板
template <typename T>
class Container {
public:void print() { std::cout << "General Container" << std::endl; }
};// 全特化:针对int类型
template <>
class Container<int> {
public:void print() { std::cout << "Int Container" << std::endl; }
};
这是一个全特化,这个和函数模板特化类似,template后面跟一对<>,并且在类名后面<int>
在 C++ 中,偏特化(Partial Specialization)的语法 要求在 template
关键字后的尖括号中保留未被特化的参数,并在类名后的尖括号中指定特化的部分
偏特化有以下两种表现方式:
部分特化:将模板参数列表中的一部分参数特化
// 通用模板:两个参数
template <typename T, typename U>
class Pair {
public:void print() { std::cout << "General Pair" << std::endl; }
};// 部分特化:固定第二个参数为int
template <typename T>
class Pair<T, int> {
public:void print() { std::cout << "Pair with int: " << typeid(T).name() << std::endl; }
};
参数更进一步的限制
template <typename T>
class Container {
public:void process() { std::cout << "General Container" << std::endl; }
};// 参数限制:针对指针类型
template <typename T>
class Container<T*> {
public:void process() { std::cout << "Pointer Container: " << typeid(T).name() << std::endl; }
};// 参数限制:针对引用类型
template <typename T>
class Container<T&> {
public:void process() { std::cout << "Reference Container" << std::endl; }
};
总结
- 类模板:全特化和偏特化均支持,用于定制类的行为。
- 函数模板:仅支持全特化,偏特化需通过函数重载替代。
- 最佳实践:优先使用函数重载处理不同参数类型,仅在必要时使用类模板特化。
- 偏特化:偏特化就是对参数的进一步限制
模板分离编译
什么是分离编译?
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程称为分离编译模式
为什么要分离编译?
方便维护和查看,直接.h头文件看函数功能,.cpp源文件看功能实现
对于普通的函数和类,我们可以进行分离编译,但函数模板和类模板不行???
我们首先回顾一个源文件如何生成目标文件
对于这个过程不熟悉的可以自行查看,或者看我的函数名重载那一篇文章
Fun.h//模板函数的声明
Fun.cpp//这里面包含模板函数
test.cpp//包头文件
头文件Fun.h
template<class T>
T add(const T&left,const T&right);
源文件Fun.cpp
template<class T>
T add(const T&left,const T&right)
{return left+right;
}
test.cpp
#include "Fun.h"
int main()
{add(1,2);add(1.0,2.0);
return 0;
}
包头文件就相当于一种承诺,会检查是否符合头文件声明函数的参数,返回类型等
但源文件是单独编译的,也就是Fun.cpp和test.cpp是单独编译的
Fun.cpp因为没有实例化的参数,所以没有实例化版本,不会生成具体的加法函数
test.cpp编译时有实例化参数,但没有函数,当它编译好,要去链接,发现没有函数地址,找不到
所以就会报链接错误
如何解决???
1.将声明和定义放到一个文件中,也就是Fun.cpp中的放入Fun.h,不要模板分离编译
这样包头文件时,就会包到test.cpp中
2.模板定义的位置显示实例化。这种方法不实用,不推荐使用
也就是直接在Fun.cpp中直接add<int>指定生成什么,这看着就很挫,你是知道test.cpp中使用什么才实例化,但在实际中是不知道的,所以这种方法不推荐
3.export关键字
大多数编译器不支持,实用性差
模板总结
优点:
1.模板复用了代码,节省了资源,更快的迭代开发,c++的标准模板库(STL)因此而产生
2.增强了代码的灵活性
缺点:
1.模板会导致代码膨胀问题,也会导致编译时间变长
2.出现模板编译错误时,错误信息非常凌乱,不易定位错误
相关文章:
C++之模板进阶(探索C++模板:非类型参数与特化技巧)
本节目标: 1.非类型模板参数 2.类模板的特化 3.类模板特化的应用之类型萃取 4.模板的分离编译 非类型模板参数 模板参数分 类型形参与非类型形参 类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称 非类型形…...
【项目记录】准备工作及查询部门
1 开发规范 1.1 前后端分离开发 现在的企业项目开发有2种开发模式:前后台混合开发和前后台分离开发。 前后台混合开发,顾名思义就是前台后台代码混在一起开发 这种开发模式有如下缺点: 1. 沟通成本高:后台人员发现前端有问题&a…...
chromedp -—— 基于 go 的自动化操作浏览器库
chromedp chromedp 是一个用于 Chrome 浏览器的自动化测试工具,基于 Go 语言开发,专门用于控制和操作 Chrome 浏览器实例。 chromedp 安装 go get -u github.com/chromedp/chromedp基于chromedp 实现的的简易学习通刷课系统 目前实现的功能ÿ…...
企业级调度器LVS
访问效果 涉及内容:浏览拆分、 DNS 解析、反向代理、负载均衡、数据库等 1 集群 1.1 集群类型简介 对于⼀个业务项⽬集群来说,根据业务中的特性和特点,它主要有三种分类: 高扩展 (LB) :单个主机负载不足的时候…...
MySQL中的重要常见知识点(入门到入土!)
基础篇 基础语法 添加数据 -- 完整语法 INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);-- 示例 insert into employee(id,workno,name,gender,age,idcard,entrydate) values(1,1,Itcast,男,10,123456789012345678,2000-01-01) 修改数据 -- 完整语法 UPDA…...
29.第二阶段x64游戏实战-技能冷却
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 上一个内容:28.第二阶段x64游戏实战-代码实现遍历技能 找技能冷却要通过一个技能cd长点的&…...
第19天-Python自动化生成PPT图文教程(基于python-pptx)
环境准备 pip install python-pptx Pillow 基础示例:批量插入图片 from pptx import Presentation from pptx.util import Inches import os from PIL import Image def create_image_slides(): # 初始化演示文稿 prs = Presentation() # 获取当前目录所…...
基于STM32的骑行语音播报系统
目录 一、前言 二、项目功能说明 三、主要元器件 四、原理图与PCB 五、手机APP 六、完整资料 一、前言 项目成品图片: 哔哩哔哩视频链接: 咸鱼商品链接: 基于STM32的骑行语音播报系统 二、项目功能说明 基础功能: 1&…...
springboot链接nacos测试
代码资料链接:https://download.csdn.net/download/ly1h1/90881498 场景说明:本次测试是springboot项目,可以链接上ncaos,将对应命名空间下的配置信息读取出俩,然后可以在接口进行返回显示。 0.环境配置 1.代码结构 …...
【初识】内网渗透——基础概念,基本工具使用
目录 一、域,工作组,域控制器,活动目录相关概念: 域环境: 工作组: 域控制器DC: 活动目录AD: 二、内网的基本场景: 三、内网渗透基本测试方案: #案例1一基本信…...
AI练习:混合圆
方法一:在圆内 1.画圆 选择椭圆工具,按住Shift键绘制正圆; CtrlC复制,CtrlF原地粘贴,按住Shift键缩小圆,移动位置; 再CtrlC,CtrlF,再按住Shift键缩小圆,移…...
心知天气 API 获取天气预报 2025/5/21
心知天气 API 获取天气预报 2025/5/21 URL格式: https://api.seniverse.com/v3/weather/now.json?key填你的秘钥&locationbeijing(这里填城市 可以用拼音)&languagezh-Hans&unitc 返回格式如下:...
PCB设计教程【入门篇】——电路分析基础-元件数据手册
前言 本教程基于B站Expert电子实验室的PCB设计教学的整理,为个人学习记录,旨在帮助PCB设计新手入门。所有内容仅作学习交流使用,无任何商业目的。若涉及侵权,请随时联系,将会立即处理 目录 前言 一、数据手册的重要…...
java上机测试错题回顾(1)
平时不能摸鱼太多,这样导致到最后不能摸鱼...... 看了看日历原来是6.12就结课了,啊哈哈,真没几天准备了,期末月你要来了吗? 1 参数传递,值传递~! 题目 以下代码的输出结果为( &a…...
HTTP相关内容
应用层 自定义应用层协议,协议:约定 1.约定好通信传输的信息 2.约定好数据的组织格式(xml, json(重点), protobuf) 也可以基于现成的应用层协议,来进行开发 协议的种类非常多(HTTP 协议属于翘楚,1.手机,2 网站) 跟正确的说,咱们现在使用的是 HTTPS 这个协议,HTTP和HTTPS …...
【笔记】排查并解决Error in LLM call after 3 attempts: (status code: 502)
#工作记录 一、问题描述 在部署运行部署对冲基金分析工具 ai-hedge-fund 时,不断出现以下报错,导致项目运行异常: Error in LLM call after 3 attempts: (status code: 502) Error in LLM call after 3 attempts: [WinError 10054] 远程主…...
基于python的机器学习(七)—— 数据特征选择
目录 一、特征选择概念 二、特征选择的方法 2.1 过滤式特征选择 2.1.1 方差分析 2.1.2 相关系数 2.1.3 卡方检验 2.2 包裹式特征选择 2.2.1 递归特征消除 2.3 嵌入式特征选择 2.3.1 决策树特征重要性 一、特征选择概念 特征选择是机器学习非常重要的一个步骤&#x…...
从电商角度设计大模型的 Prompt
从电商角度设计大模型的 Prompt,有一个关键核心思路:围绕具体业务场景明确任务目标输出格式,帮助模型为运营、客服、营销、数据分析等工作提效。以下是电商场景下 Prompt 设计的完整指南,包含通用思路、模块范例、实战案例等内容。…...
从零基础到最佳实践:Vue.js 系列(5/10):《状态管理》
引言 你是不是正在用 Vue.js 开发一个很酷的应用,然后发现组件之间的数据传递变得越来越混乱?比如,一个按钮的状态要传到好几层组件,或者多个页面需要共享同一个用户信息。这时候,状态管理就登场了!在 Vue…...
git checkout HEAD
git checkout HEAD 主要用于将工作目录和暂存区的内容重置为当前 HEAD 指向的提交状态,常用于撤销未提交的修改15。具体行为如下: 一、核心作用 恢复工作区文件 将指定文件或全部文件恢复到 HEAD 指向的提交状态,丢弃工作区中未暂存的修改…...
git工具使用
安装Git 在开始使用Git之前,需要在本地计算机上安装Git工具。Git支持Windows、macOS和Linux系统。可以从Git官方网站下载适合操作系统的安装包,并按照安装向导进行安装。 bash复制插入 # 在Linux上安装Git sudo apt-get install git# 在macOS上安装Git…...
极大似然估计与机器学习
复习概统的时候突然发现好像极大似然估计MLE与机器学习的数据驱动非常相似,都是采样样本然后估计模型参数。貌似,后知后觉的才意识到极大似然估计就是机器学习有效的数学保证 下面以拟合线性分布的最小二乘与分类问题为例推到以下如何从似然函数推导出M…...
基于 Guns v5.1 框架的分页教程
基于 Guns v5.1 框架的分页教程 第一步:Controller 层处理前端请求 在 Controller 中,需要接收 Bootstrap Table 传来的分页参数(limit, offset, sort, order)。Guns 提供了封装好的 PageFactory 类来简化 Page 对象的创建。 R…...
从零搭建SpringBoot Web 单体项目【基础篇】2、SpringBoot 整合数据库
系列文章 从零搭建SpringBoot Web单体项目【基础篇】1、IDEA搭建SpringBoot项目 从零搭建 SpringBoot Web 单体项目【基础篇】2、SpringBoot 整合数据库 目录 一、项目基础环境说明 二、数据库整合流程 1. 添加 MyBatis-Plus 相关依赖(pom.xml) 2…...
Supplemental Table 5FAM49B H-SCORE与其他临床特征的关系
以下是针对 Supplemental Table 5 中不同变量类型所需检验方法的 SPSS纯界面操作步骤(严格匹配原文统计方法): Supplemental Table 5 SPSS操作步骤 目标:分析FAM49B H-SCORE与其他临床特征的关系,按变量类型选择检验方法。 变量与检验方法对应表 变量变量类型检验方法SP…...
信息系统项目管理师考前练习4
项目范围基准变更 当客户提出新增功能需求时,项目经理首先应该: A. 立即更新范围说明书 B. 提交变更请求并评估影响 C. 要求团队加班实现 D. 拒绝变更以保持进度 答案:B 解析:所有范围变更必须走正式变更流程(第5版强调变更控制),评估影响是第一步。 混合项目管理模式…...
C语言判断素数(附带源码和解析)
素数,也称为质数,是一个大于 1 的自然数,除了 1 和它本身外,不能被其他自然数整除。换句话说,素数只有两个因子:1 和它自身。例如,2、3、5、7、11 和 13 都是素数。 素数在数学和计算机科学中扮…...
汽车电子电气架构诊断功能开发全流程解析
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...
Xilinx XCAU10P-2FFVB676I 赛灵思 Artix UltraScale+ FPGA
XCAU10P-2FFVB676I 是 AMD Xilinx 推出的 Artix UltraScale™ FPGA 器件,内部集成了约 96,250 逻辑单元,满足中等规模高性能应用的需求。该芯片采用 16 nm FinFET 制程工艺,核心电压典型值约 0.85 V,能够在较低功耗下提供高达 775…...
DS18B20 温度传感器实验探索与实践分享
DS18B20 温度传感器实验探索与实践分享 在嵌入式系统开发领域,温度监测是常见的应用场景。本次实验聚焦于 DS18B20 温度传感器,旨在掌握其工作原理、单总线通信方式,以及实现温度采集与数码管显示,同时开启温度报警功能。接下来&…...
RT_Thread——内存管理
文章目录 一、为什么要自己实现内存管理二、RT-Thread 的内存管理方法2.1 小内存管理算法2.2 slab 管理算法2.3 memheap 管理算法 三、Heap 相关的函数3.1 rt_system_heap_init3.2 rt_malloc/rt_realloc/rt_calloc2.3 rt_free2.4 rt_malloc_sethook/rt_free_sethook 一、为什么…...
Temporary failure in name resolution
这个错误 ping: baidu.com: Temporary failure in name resolution 通常表示 DNS 解析的问题,也就是说你的系统无法通过域名服务器解析 baidu.com 的 IP 地址。 解决方案: 检查 DNS 配置( 有效 ): 确保系统的 DNS 配置是正确的。你可以检查 …...
【动手学深度学习】1.4~1.8 深度学习的发展及其特征
目录 1.4. 起源1.5. 深度学习的发展1.6. 深度学习的成功案例1.7. 特点1.8. 小结 1.4. 起源 深度学习的起源可追溯至多个领域的长期发展: 统计学基础:早期统计学方法(如伯努利分布、高斯分布、最小均方算法)和估计思想(…...
深度学习之序列建模的核心技术:LSTM架构深度解析与优化策略
LSTM深度解析 一、引言 在深度学习领域,循环神经网络(RNN)在处理序列数据方面具有独特的优势,例如语音识别、自然语言处理等任务。然而,传统的 RNN 在处理长序列数据时面临着严重的梯度消失问题,这使得网…...
Gartner研究报告《Generative AI 赋能Digital Commerce的三种路径》学习心得
一、研究背景 随着生成式 AI(GenAI)技术的迅速发展,其在数字商务领域的应用受到了广泛关注。这篇研究报告深入探讨了 GenAI 在数字商务中的角色以及它如何与现有的数字商务技术相结合来发挥优势,为应用领导者提供了关于如何利用 GenAI 优化技术投资策略的见解。 二、GenA…...
解锁 YOLOv8 新潜能:EfficientViT 主干网络的优化实践与实验数据解读
文章目录 一、YOLO 系列主干网络的发展历程二、EfficientViT:YOLOv8 主干网络的新宠(一)EfficientViT 的核心优势(二)EfficientViT 在 YOLOv8 中的集成与实现 三、实验对比:EfficientViT vs. MobileNet 系列…...
【前端基础】12、CSS的overflow(visible、hidden、scroll、auto)【注:只有最基础的说明。】
一、overflow的作用 用于控制内容溢出时的行为。 二、overflow的使用 visible:超出的部分正常显示(默认设定) hidden:超出的部分隐藏显示(直接裁剪掉) scroll:超出的部分滚动显示 滚动条…...
创建一个element plus项目
当然可以!下面是一个 Vue 3 Element Plus 的最简单完整示例,它包括: 使用 <el-button> 按钮组件点击按钮后用 ElMessage 弹出提示 ✅ 1. 安装并初始化项目(如果还没创建项目) 你可以用官方推荐的方式快速创建…...
openCV1.1 Mat对象
imread(“D:\souse\duoxile.jpg”, IMREAD_COLOR); 功能: 从指定路径读取图像文件并解码为OpenCV的Mat对象 第一个参数: 文件路径 类型: const string&描述: 要读取的图像文件的绝对或相对路径示例: “D:\souse\duoxile.jpg” 或 “./images/test.png”第二个参数: 读取模…...
C++:array容器
array容器是序列容器,它的特点是:静态,固定数目。可以看作更安全的数组。 它还有一些成员函数,如begin():返回指向容器中第一个元素的随机访问迭代器。 #include<iostream>//数组容器 #…...
26、AI 预测性维护 (燃气轮机轴承) - /安全与维护组件/ai-predictive-maintenance-turbine
76个工业组件库示例汇总 AI 预测性维护模拟组件 (燃气轮机轴承) 概述 这是一个交互式的 Web 组件,旨在模拟基于 AI 的预测性维护 (Predictive Maintenance, PdM) 概念,应用于工业燃气轮机的关键部件(例如轴承)。它通过模拟传感器数据、动态预测剩余使用寿命 (RUL),并根…...
特种兵参会
出发(5.15) 有了去年去5月去深圳参加OpenTenBase工委会成立的经验,今年这个时候去广州就一定要在下午16点前起飞。恰好到了候机口有蔚来的牛屋,进去躺了一会。飞机顺利到达广州。晚上小聚 总监约了祁总,我们相识多年&…...
手搓四人麻将程序
一、麻将牌的表示 在麻将游戏中,总共有一百四十四张牌,这些牌被分为多个类别,每个类别又包含了不同的牌型。具体来说,麻将牌主要包括序数牌、字牌和花牌三大类。序数牌中,包含有万子、条子和筒子,每种花色…...
一命通关单调栈
前言 我们只是卑微的后端开发。按理说,我们是不需要学这些比较进阶的算法的,可是,这个世界就是不讲道理。最开始,想法是给leetcode中等题全通关,我又不打ACM我去天天钻研hard干嘛,于是碰见单调栈树状数组的…...
NV009NV010美光闪存颗粒NV011NV012
NV009NV010美光闪存颗粒NV011NV012 美光NV009-NV012闪存颗粒技术解析与行业应用全景 一、核心技术架构与制程突破 美光NV009至NV012系列闪存颗粒基于第九代3D TLC架构,通过垂直堆叠技术突破传统2D平面存储的物理限制。该架构将存储单元分层排列,如同将…...
线程、线程池、异步
目录 什么是线程 什么是线程池 什么是异步 异步与线程关系 JS中的异步 什么是线程 线程 Thread 是计算机执行的最小单位,是 进程 内的一个实体,可以被操作系统独立调用和执行 线程可以理解为进程内的“程序执行流”,一个进程可以包含多…...
docker面试题(4)
Docker与Vagrant有何不同 两者的定位完全不同 Vagrant类似于Boot2Docker(一款运行Docker的最小内核),是一套虚拟机的管理环境,Vagrant可 以在多种系统上和虚拟机软件中运行,可以在Windows、Mac等非Linux平台上为Docker…...
双检锁(Double-Checked Locking)单例模式
在项目中使用双检锁(Double-Checked Locking)单例模式来管理 JSON 格式化处理对象(如 ObjectMapper 在 Jackson 库中,或 JsonParser 在 Gson 库中)是一种常见的做法。这种模式确保了对象只被创建一次,同时在…...
建立java项目
java端: 在idea里面新建一个java,maven项目(springboot): 注意:JDK与java都得是一样的 添加基本的依赖项: 也可以在pom.xml中点击这个,从而跳转到添加依赖 建立三层架构: 在相应的java类中添加代码: <1.UserController package com.example.demo.controller;import com…...
Go语言内存共享与扩容机制 -《Go语言实战指南》
切片作为 Go 中的高频数据结构,其内存共享机制和自动扩容策略直接影响程序性能与行为,深入理解这两者,是高效使用切片的关键。 一、切片的内存结构回顾 切片是对底层数组的一个抽象,其本质是一个结构体: type slice …...