C++学习笔记----11、模块、头文件及各种主题(一)---- 模板概览与类模板(4)
2.2.2、显式实例化
有危险存在于有些类模板成员函数的编译错误,在隐式实例化时没有注意到。未被使用的类模板成员函数也可能包含语法错误,因为它们不会被编译到。这会使得检测代码的语法错误很困难。可以强制编译器生成所有成员函数的代码,virtual与non-virtual,通过使用explicit template instantiations。举例如下:
template class Grid<string>;
注意:Explicit template instantiations有助于发现错误,因为它们强制所有的类模板成员函数进行编译,即使没有被使用。
当使用Explicit template instantiations,不要只是尝试实例化类模板的基本类型,比如int,要用更复杂的类型,比如string,如果类模板支持这些类型的话。
2.2.3、类型的模板要求
当书写类型无关的代码时,必须假定这些类型的特定场景。例如,在Grid灯模板中,假定元素类型(用T代表)是可被析构的,copy/move可构建的,copy/move可赋值的。
当编译器尝试用被调用的类模板成员函数不支持的操作实例化模板时,代码编译失败,错误代码通常无法辨识。然而,即使想要使用的类型不支持类模板的所有成员函数要求的操作,也可以开发选择性的实例化来使用一些成员函数而不是其它的。
可以使用concept来书写编译器可以解释与验证的模板参数需求。编译器可以生成更多可读的错误,如果模板参数传递给不满足要求的模板实例。concept我们在本章后面讨论。
2.3、在文件之间发布模板代码
对于类模板,类模板定义与成员函数定义必须在使用它们的任何源文件中对编译器可见。有几项技术可以完成这个要求。
2.3.1、成员函数定义在与类模板定义同一文件中
可以将成员函数定义直接放到定义类模板自身的模块接口文件中。当在另一个使用模板的源文件中导入这个模块时,编译器具有所有需要代码的访问权限。这项技术用在了前面 Grid的实现中。
2.3.2、成员函数定义在独立的文件中
换一种方式,可以将类模板成员函数定义放至独立的模块接口分区文件中。这样也需要将类模板定义放在自身的模块接口分区中。例如,Grid类模板的主模块接口文件可能看起来像这样:
export module grid;
export import :definition;
export import :implementation;
导入与导出两个模块接口分区:definition与implementation。类模板定义定义在了definition分区:
export module grid:definition;
import std;
export template <typename T> class Grid { ... };
成员函数的实现在implementation分区,也需要导入definition分区,因为它需要Grid类模板定义:
export module grid:implementation;import :definition;
import std;export template <typename T>
Grid<T>::Grid(std::size_t width, std::size_t height)
: m_width { width }, m_height { height }
{ /* ... */ }
// Remainder omitted for brevity.
2.4、模板参数
在Grid例子中,Grid类模板有一个模板参数:在网格中保存的类型。当书写类模板时,在尖括号中指定参数,如下:
template <typename T>
该参数与函数中的参数列表类似。与函数一样,可以书写想要的任意多的模板参数的类模板。还有,这些参数不强制为类型,可以有缺省值。
2.4.1、非类型模板参数
非类型模板参数是“正常”参数,如int与指针--从函数来的比较熟悉的参数类型。然而,非类型模板参数只能是整型(char,int,long,等等),枚举,指针,引用,std::nullptr_t,auto&,auto*,浮点型,与类类型。后面这种,然而,会有许多限制,本文不再深入讨论。记住模板在编译时实例化;因此,非类型模板参数在编译时验证。这意味着这样的参数必须是常量或编译时常数。
在Grid类模板中,可以使用非类型模板参数来指定网格的高度与宽度而不是在构造函数中指定。使用非类型模板参数而不使用构造函数参数的主要优势是在代码编译前其值已知。回想一下,在编译前通过替换模板参数,编译器生成模板实例的代码。这样,可以在下面的实现中使用正常的二维数组,而不是使用动态改变大小的vector来进行线性表示。下面是修改之后的新的类模板定义:
export
template <typename T, std::size_t WIDTH, std::size_t HEIGHT>
class Grid
{
public:Grid() = default;virtual ~Grid() = default;// Explicitly default a copy constructor and copy assignment operator.Grid(const Grid& src) = default;Grid& operator=(const Grid& rhs) = default;// Explicitly default a move constructor and move assignment operator.Grid(Grid&& src) = default;Grid& operator=(Grid&& rhs) = default;std::optional<T>& at(std::size_t x, std::size_t y);const std::optional<T>& at(std::size_t x, std::size_t y) const;std::size_t getHeight() const { return HEIGHT; }std::size_t getWidth() const { return WIDTH; }private:void verifyCoordinate(std::size_t x, std::size_t y) const;std::optional<T> m_cells[WIDTH][HEIGHT];
};
现在模板参数列表有三个参数了:保存在网格中的对象类型,网格的宽度与高度。宽度与高度用于生成二维数组保存对象。下面是类模板成员函数定义:
template <typename T, std::size_t WIDTH, std::size_t HEIGHT>
void Grid<T, WIDTH, HEIGHT>::verifyCoordinate(std::size_t x, std::size_t y) const
{if (x >= WIDTH) {throw std::out_of_range { std::format("x ({}) must be less than width ({}).", x, WIDTH) };}if (y >= HEIGHT) {throw std::out_of_range { std::format("y ({}) must be less than height ({}).", y, HEIGHT) };}
}template <typename T, std::size_t WIDTH, std::size_t HEIGHT>
const std::optional<T>& Grid<T, WIDTH, HEIGHT>::at(std::size_t x, std::size_t y) const
{verifyCoordinate(x, y);return m_cells[x][y];
}template <typename T, std::size_t WIDTH, std::size_t HEIGHT>
std::optional<T>& Grid<T, WIDTH, HEIGHT>::at(std::size_t x, std::size_t y)
{return const_cast<std::optional<T>&>(std::as_const(*this).at(x, y));
}
注意先前指定Grid<T>的地方,现在要指定Grid<T,WIDTH,HEIGHT>来指定三个模板参数。
可以实例化该模板,使用如下:
Grid<int, 10, 10> myGrid;Grid<int, 10, 10> anotherGrid;myGrid.at(2, 3) = 42;anotherGrid = myGrid;println("{}", anotherGrid.at(2, 3).value_or(0));
代码看起来很棒,但是不幸的是,会有比你预期的限制更多。首先,不能用非常数的整数来指定高度与宽度。下面的代码编译不成功:
size_t height { 10 };
Grid<int, 10, height> testGrid; // DOES NOT COMPILE
如果定义height为常数,编译成功:
const size_t height { 10 };
Grid<int, 10, height> testGrid; // Compiles and works
带有正确返回类型的constexpr函数也没总是。例如,如果有一个constexpr函数返回一个size_t,可以用它来初始化模板的height参数:
constexpr size_t getHeight() { return 10; }
...
Grid<double, 2, getHeight()> myDoubleGrid;
第二个限制更要命。既然宽度与高度已经是模板参数了,它们就成为了每个网格类型的一部分。这意味着Grid<int,10,10>与Grid<int,10,11>是两种不同的类型。不能将一种类型的对象赋值给另一种类型的对象,也不能将一种类型的变量传递给期待另一种类型变量的函数。
注意:非类型模板参数成为了实例化对象的类型规格的一部分。
相关文章:
C++学习笔记----11、模块、头文件及各种主题(一)---- 模板概览与类模板(4)
2.2.2、显式实例化 有危险存在于有些类模板成员函数的编译错误,在隐式实例化时没有注意到。未被使用的类模板成员函数也可能包含语法错误,因为它们不会被编译到。这会使得检测代码的语法错误很困难。可以强制编译器生成所有成员函数的代码,vi…...
【力扣热题100】[Java版] 刷题笔记-160. 相交链表
题目:160. 相交链表 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意…...
多线程和线程同步复习
多线程和线程同步复习 进程线程区别创建线程线程退出线程回收全局写法传参写法 线程分离线程同步同步方式 互斥锁互斥锁进行线程同步 死锁读写锁api细说读写锁进行线程同步 条件变量生产者消费者案例问题解答加强版生产者消费者 总结信号量信号量实现生产者消费者同步-->一个…...
贝式计算的 AI4S 观察:使用机器学习对世界进行感知与推演,最大魅力在于横向扩展的有效性
「传统研究方法高度依赖于科研人员自身的特征和问题定义能力,通常采用小数据,在泛化能力和拓展能力上存疑。而 AI 研究方法则需要引入大规模、高质量数据,并采用机器学习进行特征抽取,这使得产生的科研结果在真实世界的问题中非常…...
容器化技术入门:Docker详解
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 容器化技术入门:Docker详解 容器化技术入门:Docker详解 容器化技术入门:Docker详解 引言 Doc…...
基于SSM(Spring + Spring MVC + MyBatis)框架的药房管理系统
基于SSM(Spring Spring MVC MyBatis)框架的药房管理系统 项目概述 功能需求 用户管理:管理员可以添加、删除、修改和查询用户信息。药品管理:支持对药品信息的增删改查操作,包括药品名称、价格、库存量等。供应商…...
在服务器里安装2个conda
1、安装新的conda 下载地址:Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 本文选择:Anaconda3-2023.03-1-Linux-x86_64.sh 安装:Ubuntu安装Anaconda详细步骤(Ubuntu22.04.1ÿ…...
web安全漏洞之ssrf入门
web安全漏洞之ssrf入门 1.什么是ssrf SSRF(Server Side Request Forgery,服务端请求伪造)是一种通过构造数据进而伪造成服务端发起请求的漏洞。因为请求是由服务器内部发起,所以一般情况下SSRF漏洞的目标往往是无法从外网访问的内系统。 SSRF漏洞形成的原理多是服务…...
《NoSQL 基础知识总结》
在当今的数据存储和管理领域,NoSQL 数据库正逐渐崭露头角,成为许多应用场景下的有力选择。今天,我们就来一起深入了解一下 NoSQL 的基础知识吧。 一、什么是 NoSQL? NoSQL,即 “Not Only SQL”,它是一种不…...
高校宿舍信息管理系统小程序
作者主页:编程千纸鹤 作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参…...
2.索引:MySQL 索引分类
MySQL中的索引是提高数据查询速度的重要工具,就像一本书的目录,可以帮助我们快速定位到所需的内容。选择适合的索引类型对数据库设计和性能优化至关重要。本文将详细介绍MySQL中常见的索引类型,并重点讲解聚集索引和二级索引的概念及应用。 1…...
sklearn红酒数据集分类器的构建和评估
实验目的: 1. 掌握sklearn科学数据包中决策树和神经网络分类器的构建 2. 掌握对不同分类器进行综合评估 实验数据: 红酒数据集 红酒数据集利用红酒的化学特征来描述三种不同类型的葡萄酒。 实验内容与要求: 解压文件得到wine数据。利用pa…...
【IC验证面试常问-4】
IC验证面试常问-4 1.11 struct和union的异同1.13 rose 和posedge 的区别?1.14 semaphore的用处是什么?1.15 类中的静态方法使用注意事项有哪些?1.16 initial和final的区别? s t o p , stop, stop,finish的区别1.17 logic,wire和re…...
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
数据集介绍 【数据集】道路事故识别数据集 8939 张,目标检测,包含YOLO/VOC格式标注。数据集中包含2种分类:{0: accident, 1: non-accident}。数据集来自国内外图片网站和视频截图。检测范围道路事故检测、监控视角检测、无人机视角检测、等&…...
书生浦语第四期基础岛L1G4000-InternLM + LlamaIndex RAG 实践
文章目录 一、任务要求11.首先创建虚拟环境2. 安装依赖3. 下载 Sentence Transformer 模型4.下载 NLTK 相关资源5. 是否使用 LlamaIndex 前后对比6. LlamaIndex web7. LlamaIndex本地部署InternLM实践 一、任务要求1 任务要求1(必做,参考readme_api.md&…...
基于ViT的无监督工业异常检测模型汇总
基于ViT的无监督工业异常检测模型汇总 论文1:VT-ADL: A Vision Transformer Network for Image Anomaly Detection and Localization(2021)1.1 主要思想1.2 系统框架 论文2:Inpainting Transformer for Anomaly Detection…...
数据库管理-第258期 23ai:Oracle Data Redaction(20241104)
数据库管理258期 2024-11-04 数据库管理-第258期 23ai:Oracle Data Redaction(20241104)1 简介2 应用场景与有点3 多租户环境4 特性与能力4.1 全数据编校4.2 部分编校4.3 正则表达式编校4.4 随机编校4.5 空值编校4.6 无编校4.7 不同数据类型上…...
运放进阶篇-多种波形可调信号发生器-产生方波-三角波-正弦波
引言:前几节我们已经说到硬件相关基础的电路,以及对于运放也讲到了初步的理解,特别是比较器的部分,但是放大器的部分我们对此并没有阐述,在这里通过实例进行理论结合实践的学习。而运放真正的核心,其实就是…...
CSS中的变量应用——:root,Sass变量,JavaScript中使用Sass变量
:root—— 原生CSS 自定义属性(变量) 在 SCSS 文件中定义 CSS 自定义属性。然后通过 JavaScript 读取这些属性。 // variables.scss :root { --login-bg-color: #293146;--left-menu-max-width: 200px;--left-menu-min-width: 64px;--left-menu-bg-…...
WPF+MVVM案例实战与特效(二十八)- 自定义WPF ComboBox样式:打造个性化下拉菜单
文章目录 1. 引言案例效果3. ComboBox 基础4. 自定义 ComboBox 样式4.1 定义 ComboBox 样式4.2 定义 ComboBoxItem 样式4.3 定义 ToggleButton 样式4.4 定义 Popup 样式5. 示例代码6. 结论1. 引言 在WPF应用程序中,ComboBox控件是一个常用的输入控件,用于从多个选项中选择一…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
