如何在C ++模块系统中处理模板?

时间:2017-05-09 04:52:30

标签: c++ c++20 c++-modules

我正在阅读论文A Module System for C++ 了解C ++模块,这是C ++的一个提议功能。

我无法完全理解此模块架构如何导出模板。

有什么想法吗?

1 个答案:

答案 0 :(得分:22)

目前C ++实现实际上只有两个"事物"对应于代码:我们人类编写和编辑的源代码,以及编译器根据源代码吐出的汇编。

因为C ++模板是"具体化"所以为每个模板实例化吐出单独的程序集。因此,在定义模板的地方不能生成任何组件,只能在它们被使用的地方生成。这就是为什么模板必须在头文件中,所以它们基本上可以复制粘贴到使用点(所有#include都是真的)。​​

这个想法是拥有代码的第三个表示。想象一下,在之后,编译器内部有一些内部表示它已解析代码但之前它开始生成程序集。 """它产生的最终是某种抽象语法树(AST)的表示。它基本上完全是您的程序,从最简单的人类形式映射到最简单的计算机形式。

这大致是模块背后的想法(或者至少是它们的实现)。你拿你的代码,并吐出一些代表AST的文件。此AST完全代表您的程序,因此它完全无损。它知道您声明的模板的所有内容,依此类推。加载模块时,它只会加载此文件,编译器可以使用它,就像它具有所有可用源一样。但是,将人类可读源转换为AST的步骤实际上是非常昂贵的一步。从AST开始可以快得多。

如果您只有一个翻译单元,这将会更慢。毕竟,解析 - > codegen仍然比解析更快 - >序列化 - >反序列化 - >代码生成。但是说你有10个翻译单元都是#include vector。您将在向量中解析代码10次。此时,序列化/反序列化的额外成本被您只需要解析一次这一事实所抵消(反序列化可以比解析快得多;这种数据格式将专门设计用于快速反序列化,而源代码是旨在可读,向后兼容等)。

预编译的标题在某种意义上是模块的预览:https://clang.llvm.org/docs/PCHInternals.html