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控件是一个常用的输入控件,用于从多个选项中选择一…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
