问题描述
我们在 C++20 中有模块,我们可以完全删除代码中的 #include
吗?
比如我们可以写
import boost.asio;
...
代替
#include <boost/asio.hpp>
...
过去我们需要这些步骤来安装一个库:
在 C++20 中,我们可以:
- 编译所有源代码,但每个源文件可能会生成一个对象 (.o) 和一个编译模块接口 (CMI)。对于 gcc,它们有 .gcm 后缀。
- 将对象 (.o) 打包到库(.a 或 .so)中。
- 将库文件安装到
/usr/lib
中。 - 将 CMI 安装到某个路径中。
但是使用 CMI 发布您的库会导致问题:
- 我们没有专门的文件夹来放置 CMI(我猜可能是
/usr/include/c++-modules
)。 - 不同的编译器产生不同的 CMI。开发人员为他们的库提供不同版本的 CMI 是很糟糕的。
- 如果我们根据模块 B 编译模块 A,但使用不同的编译标志会怎样?不同的标志可能不会引起您的注意,但可能会导致潜在的错误。
用 CMI 替换标头不是一个好方法。那么我们如何才能从 C++ 中彻底删除头文件呢?
我不是在谈论标准库,因为在 c++23 中引入了模块化的 c++ 标准库。
解决方法
模块并不是一种二进制分发机制;您应该期望提供模块接口文件(即,编译为库中目标文件的相同文件, 它们不是头文件)以非常头文件的方式,并将 CMI 生成和缓存留给客户端的编译器和构建树(分别)。因此,只有在使用给定模块的第一个翻译单元之后,每个客户端才能实现构建速度优势。
在实践中很可能会出现其他共享机制,但这里的重要部分是它本质上并不比现有的构建策略更复杂或更不兼容。