问题 模块会使模板编译更快吗?


模块会使模板编译更快吗?模板(通常)必须只是标题,最终驻留在#includer的翻译单元中。

相关:预编译头是否可以更快地进行模板编译?


8311
2017-08-03 20:26


起源

什么是模块,用C ++术语? - Mark B
open-std.org/JTC1/SC22/wg21/docs/papers/2012/n3347.pdf - David


答案:


根据模块提案,从您引用的论文中,它是添加模块的三个主要目标中的第一个:

1简介

模块是一种封装库并封装其实现的机制。   它们与翻译单元和标题文件的传统方法有所不同   所有实体都只在一个地方定义(甚至是类,模板等)。这张纸   提出了一个模块机制(有点类似于Modula-2)有三个   主要目标:

  • 显着改善大型项目的建设时间
  • 在接口和实现之间实现更好的分离
  • 为现有库提供可行的过渡路径   虽然这些是推动目标,但该提案还解决了许多其他长期存在的实际C ++问题(初始化排序,运行时性能等)。

那么,他们如何实现这些目标呢?从第4.1节开始:

由于标题文件通常包含在许多其他文件中,因此   构建周期的增长通常相对于源的总量是超线性的   码。如果问题没有得到解决,那么使用模板可能会变得更糟   增加和更强大的声明设施(如概念,合同编程,   等)被添加到语言中。

模块通过替换文本包含机制来解决这个问题   处理时间与预编译的处理时间大致成比例   模块附件机制(其处理时间 - 适当实施时 -   大致与导入的声明数成比例)。客户的财产   当私有模块定义发生变化时,无需重新编译翻译单元   保留。

换句话说,解析这些模板所花费的时间至少只进行一次而不是N次,这已经是一个巨大的进步。

后面的部分描述了诸如显式实例化之类的改进。直接改进的一件事是自动模板实例化,如5.8节所述。在这里,所有可以保证的是与预编译头文件完全相同的好处:“两个模块Set和Reset都必须实例化Lib :: S,实际上它们都在它们的接口文件中公开了这个实例化。”但该提案随后为ODR问题提供了一些可能的技术解决方案,其中至少有一些也解决了多实例化问题,在当今世界可能无法实现。例如,所提出的查询实例化的类型已被反复尝试,并且通常认为使用今天的模型很难做到正确,但模块可能使其可行。没有证据表明今天不可能做到正确,只是体验它很难,并且没有证据证明模块会更容易,只是它可能是合理的可能性。

这符合提案中从未明确说明的一般含义,但是在背景中:使编译更简单意味着我们可以在此过程中获得新的优化(直接,因为它更容易推断发生了什么,或间接地,因为一旦没有这么大的痛苦,就会有更多的人处理这个问题。

总之,模块可以并且肯定会使模板编译更快,如果没有其他原因,模板定义本身只需要解析一次。如果没有模块,它们可能会带来其他不可能或更难以实现的好处,但这可能无法保证。


12
2017-08-03 20:40



我不认为我是唯一一个会这样想的人 不 说它会改善模板的构建时间。它说实体(包括模板)在一个地方定义,而模块将显着改善构建时间。我不会从中推断出其他任何东西。 怎么样 他们可以改进模板构建时间是我应该问的问题。 - David
好吧,你可以阅读文档的其余部分。我将编辑我的答案以添加一个样本报价。 - abarnert
我不确定是否遵循,但可以从模块导出模板类,而无需指定导出的类型。即SDL中的矢量,算法和所有内容都可以作为模块导出? - Viktor Sehr


预编译头是否可以更快地进行模板编译?

没有;它制作模板 不编译。这是PCH和模块的全部要点:停止编译所有内容。

我们的想法是将“加载C ++文本并编译”为“加载C ++符号”。模块是PCH的一种通用形式。

现在,你还有成本 实例化 模板(除非它们在PCH /模块中实例化)。但是删除了编译C ++模板代码的成本。


0
2017-08-03 22:22



我虽然“编译”包含模板实例化。我...确实确实如此。 - Mooing Duck
@MooingDuck:编译和实例化不是一回事。编译从C ++文本到内部存储器表示。实例化从内部存储器表示到实际的C ++符号(具有名称的函数和对象)和实现。 - Nicol Bolas
根据C ++规范,编译从将物理源文件字符映射到基本字符集开始,并以与外部引用的链接结束。所以是的,模板实例化完全是编译的一部分。 - Mooing Duck
@MooingDuck:当然,PCH和模块也不是标准的。因此,在标准化语言方面谈论它很难。 - Nicol Bolas
我确信无论PCH和模块发生什么,它们都将成为编译的一部分,因为 从文本到可执行文件的整个过程是编译。 - Mooing Duck


我不知道模块,但我知道gcc甚至现在提供预编译头文件,就像许多其他编译器一样。预编译头可以包含模板描述的非常有效的机器可读版本,因此当包含头时可用时,可以跳过许多编译步骤,这对于仅源文本的未编译头通常是必需的。

模块论文讨论了预编译的接口文件,因此我假设当前预编译的头文件和新的预编译接口文件将提供可比较的性能。从纯文本可移植模块描述创建这样的文件可能会更有效,因为它可以节省时间,因为语言语法的限制。它将更加标准化,因此更多标头将获得预编译的好处。目前的项目很少预先编译多个头文件,根据我的经验,跨项目预编译头文件甚至更少。


-1
2017-08-03 21:12