【C++20】模块

news2024/11/24 14:38:48

模块

C++语言从一开始便继承了C语言的include头文件机制,通过包含头文件的方式来引用其他组件的代码,这些头文件通常包含了该组件相关的接口声明。但使用头文件通常伴有如下问题:

  • 不够清晰
  • 不够清晰
  • 同名符号覆盖问题

C++20提供了模块特性,一个将库与软件组件化的现代解决方案,它能够像头文件一样在源代码间共享符号,与头文件不同的地方在于,模块并不会泄露宏的定义以及一些私有的实现细节。模块容易被组合,它们能够实现精确的控制按需将接口暴露给导入它们的源文件,并且不会因为导入顺序、宏定义等改变一个模块的语义。

  • 模块提供了头文件无法做到的额外的安全保证,编译器与链接器一起协作来避免一些潜在的名称冲突问题,并且能够保证一处定义原则。
  • 模块由一系列源文件所组成,它们能够被独立导入该模块的源文件编译。模块只需要编译一次,它编译的结果就会被存储到一个二进制文件中,该文件里记录了所有导出的符号,例如函数与模板。当某个源文件导入该模块时,这个二进制文件会被读取,读取二进制文件要比解析头文件快,并且能够在项目的每一个导入该模块的源文件中复用。

Hello World模块

微软的编译器却对标准库进行了模块化,通过使用import关键字导入一个模块

import std.core;//导入标准库模块
int main()
{
    std::cout <<"Hello World\n";
}

上述代码通过importstd.core导入标准库的一些输入输出流的模块,MSVC提出了如下几种标准模块:
• std.regex提供了正则表达式相关的支持。
• std.filesystem提供了文件系统相关的支持。
• std.memory提供了智能指针等模块支持。
• std.threading提供了并行相关的支持。
• std.core提供剩余标准库的支持。

定义一个模块

使用import语句可以导入一个已有的模块,并使用那个模块中导出的接口。定义一个模块也相当简单,通常一个模块由一个接口文件和零到数个源文件组成,如果程序员在一个接口文件中声明并实现所有接口,那么也可以不再提供源文件。

创建一个数学模块,它通过math.mpp提供接口文件,内容如下

export module math;//使用export module表达对外模块名,同时表明这是一个接口文件
export template<typename T>//导出的一个接口
T square(T x){return x * x;}

过在接口文件中使用“export module模块名;来声明一个模块,这个模块名就是后续可以被用户导入的名字

如果需要对square的模板参数进行约束,例如使用标准库concept中的integral概念来约束时只能接受整数类型的参数,此时需要如何做?在模块的接口文件或源文件中提供了全局模块片段(global module fragment),它是专门在这个片段中处理头文件的预处理包含指令,这部分内容并不归模块所有,也不会导出,因此头文件仅仅是实现细节所需。

module; //全局模块片段
#include <concept>

export module math; //对外模块名
export template<std::integral T>//导出的一个接口
T square(T x){return x * x;}

在模块的接口或实现文件中,仍然可以导入其他模块,以便实现所需要的行为。例如,使用import导入标准库头文件

export module math;
import <concept>

若将实现从接口文件中拆分到源文件中,代码如下

//接口文件math.mpp
export module math;
export int square(int x); 

//实现文件math.cpp
module math; 
int square(int x){return x * x;}

在实现文件中,首先用module声明它所属的模块。接着square函数无须使用export进行修饰,export只能位于接口文件中

模块分区

如果一个模块的接口过大,可以进一步考虑将它们分解成一个个小的模块分区,这些模块分区拥有自己的接口文件,然后在主接口模块单元进行组合并导出它们。模块分区名在模块名后通过冒号(:)指明

考虑一个shape模块,矩形由两个点组成,并且提供接口求矩形的长、宽以及面积。为了展示模块分区,将点和长方形作为两个独立的模块分区,分别被命名为shape:point以及shape:rectangle

点模块分区的接口文件point.mpp

//export module表明是个接口文件
//:表明是个模块分区
export module shape:point;
export struct Point{
    int x , y;
};

模块分区的接口文件就和主接口文件一样,通过使用export module表明,唯一的区别在于模块名中的“:”,它分割了模块名与分区名。模块分区只能被同一个模块下的其他文件所导入,例如后续需要使用该模块分区的矩阵模块分区

矩阵模块分区的接口文件rectangle.mpp

export module shape:rectangle;
import:point;
export struct Rectangle{
    Point topLeft , bottomRight;
    int width();
    int hehght();
    int area();
};

主接口模块文件shape.mpp的职责是直接或间接地导出它所有的分区

export module shape;
export import :point;
export import :rectangle

私有片段

模块分区名以冒号(:)分割,而“:private”拥有额外的语义,它表达了模块的私有片段。顾名思义,当程序员不想提供额外的实现文件时,这些实现部分可以放到接口文件的私有片段中。当使用私有片段时,则无法再对模块进行分区,换句话说私有片段只能在模块主接口文件中使用,这个模块仅仅由这一个文件组成

module :private;//私有片段
template<std::integral T>//导出的一个接口
T square(T x){return x * x;}

测试代码

import <iostream>
import shape
int main()
{
    Rectangle r{{1,2},{3,4}};
    std::cout << r.area() << std::endl;
    std::cout << r.width() << std::endl;
    std::cout << r.height() << std::endl;
}

模块样板文件

模块的主接口文件,样板如下
在这里插入图片描述

模块的分区接口文件,样板如下
在这里插入图片描述

模块的分区接口文件,样板如下
在这里插入图片描述

注意事项

目前,GCC的模块在导入标准库头文件时,可能会存在编译问题,但它对分区支持比较好


参考资料 :《C++20高级编程》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1183404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

本地生活新赛道-视频号团购怎么做?

目前有在做实体行业的商家一定要看完&#xff0c;只要你进入了这个本地生活新的赛道&#xff0c;那你的生意自然会源源不断&#xff0c;那这个赛道又是什么呢&#xff1f; 这就是十月份刚刚上线的视频号团购项目&#xff0c;开通团购之后&#xff0c;就可以通过发短视频&#…

排序:堆排序(未完待续)

文章目录 排序一、 排序的概念1.排序&#xff1a;2.稳定性&#xff1a;3.内部排序&#xff1a;4.外部排序&#xff1a; 二、插入排序1.直接插入排序 二、插入排序堆排序 排序 一、 排序的概念 1.排序&#xff1a; 一组数据按递增/递减排序 2.稳定性&#xff1a; 待排序的序列…

postman中文乱码

在header中添加这两个&#xff1a; Content-Type application/json;charsetUTF-8 Accept application/json;charsetUTF-8

『昆仑天工』4款AI产品开源!提供API对接!

在文章开篇&#xff0c;小圈先介绍下 昆仑万维 公司旗下的AI大模型**『天工』**&#xff0c;它是由昆仑万维自研的双千亿级大语言模型&#xff0c; 也是国内首个对标ChatGPT的双千亿级大语言模型&#xff0c;可满足文案创作、知识问答、代码编程、逻辑推演、数理推算等需求。 …

自制宏正(ATEN)KVM CS1708i固件升级线

因为宏正 CS1708i KVM年代相对久远&#xff0c;最近通过Web进行远程管理时发现页面不支持最新的EDGE浏览器&#xff0c;官方有较新的固件&#xff0c;但是需要专用的RJ11接头的升级串口线才能进行升级。网上目前无法买到&#xff0c;在网上找到对应的资料&#xff0c;用RJ11 4P…

ansible第一天

ansible 第一天 以上主机使用rhel-8.2-x86_64-dvd.iso镜像&#xff0c;配置ip、yum源&#xff0c;关闭防火墙和selinux规则 安装中文包&#xff0c;重启生效 [rootcontrol ~]# yum -y install langpacks-zh_CN.noarch && reboot 配置名称解析 [rootcontrol ~]# echo…

拓展企业客户群:如何使用企业联系方式查询API帮助在社交媒体上寻找潜在客户

前言 在当今竞争激烈的商业环境中&#xff0c;拓展企业客户群已经成为许多企业的首要任务之一。在这种情况下&#xff0c;使用企业联系方式查询API可以帮助企业在社交媒体上寻找潜在客户。本文将探讨如何使用企业联系方式查询API拓展企业客户群。 企业联系方式查询API简介 首…

linux rsyslog介绍

Rsyslog网址&#xff1a;https://www.rsyslog.com/ Rsyslog is the rocket-fast system for log processing. It offers high-performance, great security features and a modular design. While it started as a regular syslogd, rsyslog has evolved into a kind of swis…

【物联网】继续深入探索ADC模拟转数字的原理——Flash ADC流水线ADC逐次逼近型SAR ADC

这篇文章主要弥补上一篇关于ADC的不足&#xff0c;更加深入了解ADC数模转换器的工作原理&#xff0c;举例常见的三种ADC&#xff0c;分别为Flash ADC&流水线ADC&逐次逼近型SAR ADC。 【物联网】深入了解AD/DA转换技术&#xff1a;模数转换和数模转换 文章目录 一、模拟…

休眠和睡眠有哪些区别?如何让电脑一键休眠?

电脑中有休眠和睡眠&#xff0c;那么它们有什么区别呢&#xff1f;下面我们就通过本文来了解一下。 休眠和睡眠的区别 电脑在睡眠状态时&#xff0c;会切断内存之外的设备电源&#xff0c;电脑会进入睡眠状态&#xff0c;当再次唤醒电脑后&#xff0c;不会影响睡眠前保存好的工…

Git中的 fork, clone,branch

一、是什么 fork fork&#xff0c;英语翻译过来就是叉子&#xff0c;动词形式则是分叉&#xff0c;如下图&#xff0c;从左到右&#xff0c;一条直线变成多条直线 转到git仓库中&#xff0c;fork则可以代表分叉、克隆 出一个&#xff08;仓库的&#xff09;新拷贝 包含了原来…

Swing 程序设计

概述 String包的层次结构和继承关系如下 常用的Swing组件如下表 Swing常用窗体 JFrame 窗体 JFrame 类的常用构造方法包括以下两种形式&#xff1a; public JFrame&#xff08;&#xff09;&#xff1a;创建一个初始不可见、没有标题的窗体。public JFrame(String title)…

Java并发编程第11讲——AQS设计思想及核心源码分析

Java并发包&#xff08;JUC&#xff09;中提供了很多并发工具&#xff0c;比如前面介绍过的ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore、FutureTask等锁或者同步部件&#xff0c;它们的实现都用到了一个共同的基类——AbstractQueuedSynchronizer&…

element分页

获取数据信息&#xff0c;这是表格和分页内容 <el-col :span"24"><div class"grid-content bg-purple-dark"><el-table :data"tableData" stripe style"width: 100%"><el-table-column prop"xuhao" l…

WorkPlus:企业数字化底座,统一数字化办公入口

在企业数字化转型的潮流下&#xff0c;统一入口的移动数字化底座成为了企业提高工作效率和迈向数字化时代的关键要素。在这个领域&#xff0c;WorkPlus凭借其独特的定位和功能&#xff0c;成为了企业微信、钉钉、飞书等类似产品中的完美选择&#xff0c;为企业提供了统一入口的…

旋转矩阵-数学理论

目录 概述 一、固定旋转&#xff08;Fix Angles&#xff09; 二、欧拉旋转&#xff08;Euler Angle&#xff09; 三、旋转矩阵小结 四、参考 概述 旋转矩阵是姿态的一种数学表达方式&#xff0c;或者笼统说变换矩阵是一种抽象的数学变量。其抽象在于当你看到…

【深度学习】卷积层填充和步幅以及其大小关系

参考链接 【深度学习】&#xff1a;《PyTorch入门到项目实战》卷积神经网络2-2&#xff1a;填充(padding)和步幅(stride) 一、卷积 卷积是在深度学习中的一种重要操作&#xff0c;但实际上它是一种互相关操作&#xff0c;&#xff0c;首先我们来了解一下二维互相关&#xff…

Redis主从配置和哨兵模式

主从简介 1、主从 – 用法 像MySQL一样&#xff0c;redis是支持主从同步的&#xff0c;而且也支持一主多从以及多级从结构。 主从结构&#xff0c;一是为了纯粹的冗余备份&#xff0c;二是为了提升读性能&#xff0c;比如很消耗性能的SORT就可以由从服务器来承担。 redis的主…

oracle-sql语句解析类型

语句执行过程&#xff1a;1. 解析(将sql解析成执行计划) 2.执行 3.获取数据(fetch) 1. shared pool的组成。 share pool是一块内存池。 主要分成3块空间。free&#xff0c; library(库缓存&#xff0c;缓存sql以及执行计划)&#xff0c;row cache(字典缓存) select * from v…

云贝教育 |【PostgreSQL PGCA】pg15安装pg_hint_plan扩展包

pg15安装pg_hint_plan扩展包 pg当前是支持HINT固定执行计划&#xff0c;需要通过扩展包pg_hint_plan来实现 一、扩展包下载&#xff1a; Releases ossc-db/pg_hint_plan GitHub 二、选择v15版本 pg_hint_plan15 1.5.1 is released pg_hint_plan15 1.5.1 is released. This…