C++中的extern template有什么特殊用途?
- 内容介绍
- 文章标签
- 相关推荐
extern template 是 C++11 引入的一项调整特性,专门用于控制模板实例化的时机和位置。它可以显式声明某个模板专门化在当前翻译单元中不需要生成实例,而把实例化工作交给其它 TU 来完成。怎么说呢,
至于使用者痛点,编译时间与二进制体积爆炸
在大型项目中,同一个模板被多文件引用时每个文件都会触发一次隐式实例化。导致:
- 编译时间显著增长。
- 目标文件中出现重复代码,最终二进制体积膨胀。
这些问题在持续集成、频繁迭代开发还有资源受限设备上尤为突出。
说到主要概念,声明 vs 定义
extern template class MyTemplate
template class MyTemplate;// 明确实例化定义
注意:
- 声明与定义必须出现在不同的 TU。老实说,
- 如果同一 TU 同时出现声明和定义。则定义会覆盖声明,否则会导致链接错误。说起来,
至于示例。减少重复实例化
// Header: my_template.h
#pragma once
template
struct X { /* ... */ };
extern template struct X;// Source 1: a.cpp
#include "my_template.h"
void foo { X{};}
// Source 2: b.cpp
#include "my_template.h"
template struct X;// Linker will resolve all references to X
// without generating duplicate code in a.cpp and b.cpp.
常用方法与常见陷阱
-
何时使用:
- 模板类/函数只在少数几个地方显式使用。
- A库想要把所有实现放在一个共享对象中,以减小客户端的编译负担。
- .NET/C++/Qt 等框架内部经常利用 extern template 做性能调整。
-
Avoid以下错误:
- Mistakenly putting extern on a non-template entity.
- Nesting extern template inside inline functions .
- Doubly declaring same specialization in two different headers.
- ODR 违规警告:- 在某些情况下如果你在一个 TU 用 extern 声明了某个模板。但没有提供对应的显式实例化定义,在链接阶段就会出现未定义引用;相反,如果多个 TU 都对同一模板进行显式实例化且没有 extern 声明。也会产生多重定义错误,
-
C++17 的改进:- C++17 引入了
<> 用于标记已实例化的模板,但仍然建议通过 extern + explicit instantiation 来管理大规模项目中的代码量。 - Pitfall:不能用 extern 对普通函数做声明再重新定义为非模板函数,否则会违反 ODR 并导致不可预知行为。
让编译器帮你做 “按需” 实例化
extern template 是 C++11 引入的一项调整特性,专门用于控制模板实例化的时机和位置。它可以显式声明某个模板专门化在当前翻译单元中不需要生成实例,而把实例化工作交给其它 TU 来完成。怎么说呢,
至于使用者痛点,编译时间与二进制体积爆炸
在大型项目中,同一个模板被多文件引用时每个文件都会触发一次隐式实例化。导致:
- 编译时间显著增长。
- 目标文件中出现重复代码,最终二进制体积膨胀。
这些问题在持续集成、频繁迭代开发还有资源受限设备上尤为突出。
说到主要概念,声明 vs 定义
extern template class MyTemplate
template class MyTemplate;// 明确实例化定义
注意:
- 声明与定义必须出现在不同的 TU。老实说,
- 如果同一 TU 同时出现声明和定义。则定义会覆盖声明,否则会导致链接错误。说起来,
至于示例。减少重复实例化
// Header: my_template.h
#pragma once
template
struct X { /* ... */ };
extern template struct X;// Source 1: a.cpp
#include "my_template.h"
void foo { X{};}
// Source 2: b.cpp
#include "my_template.h"
template struct X;// Linker will resolve all references to X
// without generating duplicate code in a.cpp and b.cpp.
常用方法与常见陷阱
-
何时使用:
- 模板类/函数只在少数几个地方显式使用。
- A库想要把所有实现放在一个共享对象中,以减小客户端的编译负担。
- .NET/C++/Qt 等框架内部经常利用 extern template 做性能调整。
-
Avoid以下错误:
- Mistakenly putting extern on a non-template entity.
- Nesting extern template inside inline functions .
- Doubly declaring same specialization in two different headers.
- ODR 违规警告:- 在某些情况下如果你在一个 TU 用 extern 声明了某个模板。但没有提供对应的显式实例化定义,在链接阶段就会出现未定义引用;相反,如果多个 TU 都对同一模板进行显式实例化且没有 extern 声明。也会产生多重定义错误,
-
C++17 的改进:- C++17 引入了
<> 用于标记已实例化的模板,但仍然建议通过 extern + explicit instantiation 来管理大规模项目中的代码量。 - Pitfall:不能用 extern 对普通函数做声明再重新定义为非模板函数,否则会违反 ODR 并导致不可预知行为。

