模块会让模板编译更快吗?模板(通常)必须只是标题,并且最终驻留在#includer 的翻译单元中。
相关:预编译的头文件是否使模板编译更快?
根据模块提案,从您引用的那篇论文中,它是添加模块的三个主要目标中的第一个:
1 简介
模块是一种打包库并封装其实现的机制。它们与翻译单元和头文件的传统方法的不同之处主要在于所有实体都被定义在一个地方(甚至是类、模板等)。本文提出了一种模块机制(有点类似于 Modula-2),它具有三个主要目标:
- 显着缩短大型项目的构建时间
- 在接口和实现之间实现更好的分离
- 为现有库提供可行的过渡路径 虽然这些是驱动目标,但该提案还解决了许多其他长期存在的实际 C++ 问题(初始化排序、运行时性能等)。
那么,他们如何才能实现这些目标呢?好吧,从第 4.1 节开始:
由于头文件通常包含在许多其他文件中,因此构建周期的增长相对于源代码的总量通常是超线性的。如果问题没有得到解决,随着模板使用的增加和更强大的声明性工具(如概念、合同编程等)被添加到语言中,它可能会变得更糟。
模块通过将文本包含机制(其处理时间大致与包含的代码量成正比)替换为预编译的模块附件机制(其处理时间 - 如果正确实施 - 大致与导入声明的数量成正比)来解决这个问题。可以保留私有模块定义更改时不需要重新编译客户端翻译单元的属性。
换句话说,至少解析这些模板所花费的时间只做了一次,而不是 N 次,这已经是一个巨大的进步。
后面的部分描述了诸如显式实例化之类的改进。正如 5.8 节所承认的,这并没有直接改进的一件事是自动模板实例化。在这里,所有可以保证的好处与您从预编译头文件中获得的好处完全相同:“模块 Set 和 Reset 都必须实例化 Lib::S 并且实际上都在它们的接口文件中公开了这个实例化。” 但该提案随后为 ODR 问题提供了一些可能的技术解决方案,其中至少一些还解决了多实例化问题,在当今世界可能无法实现。例如,建议的查询实例化类型已被反复尝试,通常认为很难与今天的模型相匹配,但模块可能使其可行。没有证据证明它
这符合提案中从未完全说明但在后台存在的一般含义:使编译更简单意味着我们可能会在过程中获得新的优化(直接,因为它更容易推理正在发生的事情,或间接地,因为一旦没有那么大的痛苦,就会有更多的人解决这个问题)。
总之,模块可以而且肯定会使模板编译更快,如果没有其他原因,模板定义本身只需要解析一次。它们可能会带来其他好处,如果没有模块,这些好处要么是不可能的,要么更难做到,但这可能无法保证。
预编译的头文件会使模板编译更快吗?
不; 它使模板无法编译。这是 PCH 和模块的全部要点:停止编译所有内容。
这个想法是将“加载 C++ 文本并编译”变成“加载 C++ 符号”。模块是 PCH 的一种通用形式。
现在,您仍然需要实例化模板的成本(除非它们是在 PCH/模块中实例化的)。但是编译 C++ 模板代码的成本被消除了。
我不了解模块,但我知道 gcc 甚至现在也提供预编译的头文件,许多其他编译器也是如此。预编译的标头可以包含模板描述的非常有效的机器可读版本,因此当包含标头时可用时,可以跳过许多编译步骤,这通常是纯源文本未编译标头所需的。
模块文件讨论了预编译的接口文件,所以我假设当前的预编译头文件和新的预编译接口文件将提供相当的性能。从纯文本可移植模块描述创建这样的文件可能会更有效,因为由于语言语法的限制,它可以节省时间。而且它会更加标准化,所以更多的头文件会从预编译中受益。当前项目很少预编译多个头文件,而跨项目预编译头文件在我的经验中更为罕见。