Lv.的博客

C++11 : 外部模板(Extern Template)

在C++98/03语言标准中,对于源代码中出现的每一处模板实例化,编译器都需要去做实例化的工作;而在链接时,链接器还需要移除重复的实例化代码。显然,让编译器每次都去进行重复的实例化工作显然是不必要的,并且连接器也因此受累。
在现实编码世界里,一个软件的实现可能会在很多代码块中使用同一种类型去实例化同一个模板。此时,如果能够让编译器避免此类重复的实例化工作,那么可以大大提供编译器的工作效率。因此,人们迫切需要一种手段(一种声明方式)来告诉编译器“该处出现的模板实例化工作已在其它编译单元中完成,不再需要进行实例化”。
于是,一个新的语言特性————外部模板(Extern Template)————被纳入到C++0x标准中。
在C++98/03中,已经有一个叫做显示实例化(Explicit Instantiation)的语言特性,其目的是指示编译器立即进行模板实例化操作(即强制实例化)。而外部模板语法就是在显示实例化指令的语法基础上进行修改得到的:通过在显示实例化指令前添加前缀extern,从而得到外部模板的语法。
显示实例化语法:template class vector<MyClass>;
外部模板语法:extern template class vector<MyClass>;
一旦在一个编译单元中使用了外部模板声明(如extern template class vector<MyClass>;),那么编译器在编译该编译单元时,会跳过与该外部模板声明匹配的模板实例化(如vector<MyClass>)。
因此,在C++0x中,“模板的显示实例化指令、外部模板指令和使用”可以类比为“全局变量的定义、声明和使用”。区别仅在于,模板代表代码,而变量代表一段连续内存空间。
关于外部模板语法的一些约束:
1. 如果外部模板指令出现于一个编译单元中,那么与之对应的显示实例化必须出现于另一个编译单元中或者同一个编译单元的后续代码中。
2. 外部模板指令不能用于一个静态函数(即文件域函数),但可以用于类静态函数。(注:这一点是显而易见的,因为静态函数没有外部连接属性,不可能在本编译单元之外出现)。
3. 外部模板指令应用于类的成员,而不是类本身。(注:既然已经作用于类的所有成员了,也就相当于作用于类了)
4. 外部模板对于内联函数是否有用,没有明确规定,但鼓励编译器实现。
编译器支持
Visual Studio好像是从VS2008(VC9)开始支持外部模板的。GCC似乎很早就支持外部模板了,但不清楚具体是在哪一个版本中加入的,至少4.3及其以后的版本是支持的。
Ref
1. Adding "extern template" (version 2)
2. C++0x,Extern Template @ Wiki

posted @ 2015-05-09 14:41  Avatarx  阅读(6217)  评论(0编辑  收藏  举报