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控件是一个常用的输入控件,用于从多个选项中选择一…...

速盾:怎么使用cdn加速?
CDN(Content Delivery Network)即内容分发网络,是一种通过在网络各处部署节点来缓存和传输网络内容的技术。通过使用CDN加速,可以提高网站的访问速度、减轻服务器负载、提供更好的用户体验。 使用CDN加速的步骤如下: …...

C++ 优先算法 —— 三数之和(双指针)
目录 题目:三数之和 1. 题目解析 2. 算法原理 ①. 暴力枚举 ②. 双指针算法 不漏的处理: 去重处理: 固定一个数 a 的优化: 3. 代码实现 Ⅰ. 暴力枚举(会超时 O(N)) Ⅱ.…...

YOLOv7-0.1部分代码阅读笔记-yolo.py
yolo.py models\yolo.py 目录 yolo.py 1.所需的库和模块 2.class Detect(nn.Module): 3.class IDetect(nn.Module): 4.class IAuxDetect(nn.Module): 5.class IBin(nn.Module): 6.class Model(nn.Module): 7.def parse_model(d, ch): 8.if __name__ __main__…...

【缓存与加速技术实践】Web缓存代理与CDN内容分发网络
文章目录 Web缓存代理Nginx配置缓存代理详细说明 CDN内容分发网络CDN的作用CDN的工作原理CDN内容的获取方式解决缓存集中过期的问题 Web缓存代理 作用: 缓存之前访问过的静态网页资源,以便在再次访问时能够直接从缓存代理服务器获取,减少源…...

MySQL的约束和三大范式
一.约束 什么是约束,为什么要用到约束? 约束就是用于创建表时,给对应的字段添加对应的约束 约束的作用就是当我们用insert into时,如果传入的数据有问题,不符合创建表时我们定的规定,这时MySQL就会自动帮…...

Unity网络通信(part7.分包和黏包)
目录 前言 概念 解决方案 具体代码 总结 分包黏包概念 分包 黏包 解决方案概述 前言 在探讨Unity网络通信的深入内容时,分包和黏包问题无疑是其中的关键环节。以下是对Unity网络通信中分包和黏包问题前言部分的详细解读。 概念 在网络通信中,…...

练习题 - DRF 3.x Overviewses 框架概述
Django REST Framework (DRF) 是一个强大的工具,用于构建 Web APIs。作为 Django 框架的扩展,DRF 提供了丰富的功能和简洁的 API,使得开发 RESTful Web 服务变得更加轻松。对于想要在 Django 环境中实现快速且灵活的 API 开发的开发者来说,DRF 是一个非常有吸引力的选择。学…...

Linux 经典面试八股文
快速鉴别十个题 1,你如何描述Linux文件系统的结构? 答案应包括对/, /etc, /var, /home, /bin, /lib, /usr, 和 /tmp等常见目录的功能和用途的描述。 2,在Linux中如何查看和终止正在运行的进程? 期望的答案应涵盖ps, top, htop, …...

Filter和Listener
一、Filter过滤器 1 概念 可以实现拦截功能,对于指定资源的限定进行拦截,替换,同时还可以提高程序的性能。在Web开发时,不同的Web资源中的过滤操作可以放在同一个Filter中完成,这样可以不用多次编写重复代码…...

Go 项目中实现类似 Java Shiro 的权限控制中间件?
序言: 要在 Go 项目中实现类似 Java Shiro 的权限控制中间件,我们可以分为几个步骤来实现用户的菜单访问权限和操作权限控制。以下是一个基本的实现框架步骤: 目录 一、数据库设计 二、中间件实现 三、使用中间件 四、用户权限管理 五…...