You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何预编译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成员函数的实例化步骤,直接链接已生成的符号。

  • 能否在预编译头中实现该操作?
    可以,但需区分两种场景:
    1. 显式实例化定义(不带extern的代码):不能放在预编译头中。因为预编译头会被多个TU包含,重复的显式实例化定义会触发链接阶段的多重定义错误。你应该把这行代码单独放在一个独立的.cpp文件中,仅编译一次。
    2. 显式实例化声明(带extern的代码):可以放在预编译头中。这样所有包含预编译头的TU都会自动获取该声明,既减少了重复代码,又能确保编译器不会重复实例化std::variant的相关方法。

内容的提问来源于stack exchange,提问作者yano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:56:04