C++20模块能否优化函数模板的编译速度?
问题描述
我平时使用函数模板时编译时长会大幅增加,朋友建议采用C++20的模块进行编译优化,但我认为这对编译速度不会有任何影响。由于不知道如何测试,特此提问:以下代码是否能优化构建流程?模板定义仍需创建并编译,难道不会产生任何变化吗?
math.ixx 代码
module; #include <typeinfo> export module math; import <iostream>; export template<typename T> T square(T x) { std::cout << typeid(T).name() << std::endl; return x * x; }
main.cpp 代码
import math; int main() { square(int()); square(double()); }
回答
你的代码确实能优化构建流程,核心原因在于模块解决了传统头文件模式下模板编译的两大痛点:
避免模板实例化的重复编译
在传统头文件模式中,每个包含模板头文件的源文件,都会重新编译模板的定义以及用到的实例。比如如果有10个源文件都用到square<int>,这个实例就会被编译10次,最后由链接器去重。而用模块的话,模板实例可以在模块编译阶段只生成一次,所有导入模块的源文件直接复用这个编译结果,无需重复劳动。减少冗余预处理工作
传统头文件的#include会把整个头文件内容(包括其依赖的其他头文件)展开到每个源文件中,带来大量重复的预处理、语法解析工作。模块的import只会导入公开的接口,不会重复处理模块内部的依赖(比如#include <typeinfo>、import <iostream>),这也能节省不少编译时间。
针对你的代码来说:编译math.ixx时,编译器会处理square模板的定义,当main.cpp导入该模块时,不需要再重新解析模板代码,也不需要重新编译square<int>和square<double>这两个实例——这些实例要么在模块编译阶段就已生成,要么编译器会缓存实例化结果,避免重复编译。
所以哪怕模板定义本身存在,模块依然能通过上述两点显著优化构建流程,在多源文件复用同一模板的大型项目中,效果会更明显。
内容的提问来源于stack exchange,提问作者montjet

