【问题标题】:How are templates handled in C++ module system?C++ 模块系统中如何处理模板?
【发布时间】:2017-10-07 06:24:31
【问题描述】:

我正在看报纸A Module System for C++ 了解 C++ 模块,这是 C++ 的一项建议功能。

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

有什么想法吗?

【问题讨论】:

  • 顺便提一下:它被提出但没有进入 C++17 标准。但它可能有一天会成为 C++ 标准功能,因为微软的 Clang 和 VS 已经支持模块,许多人希望看到模块成为 C++ 标准的一部分。
  • @Shadow 被做成了C++20。

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


【解决方案1】:

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

因为 C++ 模板是“具体化”的,所以每个模板实例化都会产生单独的程序集。因此,不能在定义模板的地方生成任何程序集,而只能在使用它们的地方生成。这就是为什么模板必须在头文件中,以便它们基本上可以复制粘贴到使用点(这就是#include 的全部内容)。

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

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

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

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

【讨论】:

  • 如果你像 VS 那样一次获取多个 C++ 文件。您只需反序列化所有需要重新编译的翻译单元的“#include ”。这就是为什么与 gcc 和 clang 相比,预编译的头文件使 VS 构建速度如此之快的原因之一。
  • @Lothar,你是说 gcc 和 clang 不能使用预编译的头文件吗?因为他们已经在那里很久了。
  • 不,我是说他们的速度不足以证明使用的合理性。实施很糟糕。通过在 Windows 上精心设计的预编译头文件,我得到了几乎 8 倍的改进。 GCC 和 clang 仅快 30%。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多