如何预编译std::variant实例化以降低C++编译耗时?
问题描述
我在C++中使用包含约100个结构体的std::variant类型,该类型在整个应用中广泛使用。编译耗时分析显示,耗时主要来自std::variant各类方法的实例化与生成,例如:
Wall Duration 18,560.314 ms Args detail "std::__variant_detail::__dtor.......
此外,有上百个翻译单元(TU)需要该类型定义,导致编译时长居高不下。
我熟悉模板的显式实例化方式,例如:
template class MyClass<XXX>;
请问能否对std::variant执行类似的显式实例化?如何让其他翻译单元依赖已链接的这些符号?能否在预编译头中实现该操作?
解决方案
- 能否对std::variant执行显式实例化?
可以。std::variant作为标准库模板类型,完全支持显式实例化语法。假设你的目标variant类型是std::variant<Struct1, Struct2, ..., Struct100>,直接写出如下显式实例化代码即可:
template class std::variant<Struct1, Struct2, /* ... 填充所有100个结构体类型 ... */>;
注意:必须保证这行代码所在的文件中,所有100个结构体都已经完成完整定义,否则编译器会抛出不完整类型的错误。
- 如何让其他翻译单元依赖已链接的符号?
在其他需要使用该std::variant的翻译单元中,通过显式实例化声明(extern template)告知编译器:该模板的实例化代码已经在别处生成,无需本地重复实例化。写法如下:
extern template class std::variant<Struct1, Struct2, /* ... 所有100个结构体类型 ... */>;
把这个声明放在所有相关TU都会包含的公共头文件里,这样每个TU编译时就会跳过std::variant成员函数的实例化步骤,直接链接已生成的符号。
- 能否在预编译头中实现该操作?
可以,但需区分两种场景:- 显式实例化定义(不带
extern的代码):不能放在预编译头中。因为预编译头会被多个TU包含,重复的显式实例化定义会触发链接阶段的多重定义错误。你应该把这行代码单独放在一个独立的.cpp文件中,仅编译一次。 - 显式实例化声明(带
extern的代码):可以放在预编译头中。这样所有包含预编译头的TU都会自动获取该声明,既减少了重复代码,又能确保编译器不会重复实例化std::variant的相关方法。
- 显式实例化定义(不带
内容的提问来源于stack exchange,提问作者yano
相关产品推荐
相关产品推荐

