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

How are templates handled in C++ module system?

本文关键字:处理 系统 C++ 模块      更新时间:2023-10-16

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

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

有什么想法吗?

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

由于C++模板是"化"的,因此将为每个模板实例化吐出单独的程序集。因此,不能在定义模板的位置生成程序集,而只能在使用模板的位置生成程序集。这就是为什么模板必须位于头文件中,以便基本上可以将它们复制粘贴到使用点(这就是 #include 的全部内容)。

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

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

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

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