猿问

使用extern模板(C ++ 11)

使用extern模板(C ++ 11)

图1:功能模板

TemplHeader.h

template<typename T>void f();

TemplCpp.cpp

template<typename T>void f(){
   //...}    //explicit instantationtemplate void f<T>();

Main.cpp的

#include "TemplHeader.h"extern template void f<T>(); //is this correct?int main() {
    f<char>();
    return 0;}

这是正确的使用方法extern template,还是仅将此关键字用于类模板,如图2所示?

图2:类模板

TemplHeader.h

template<typename T>class foo {
    T f();};

TemplCpp.cpp

template<typename T>void foo<T>::f() {
    //...}//explicit instantationtemplate class foo<int>;

Main.cpp的

#include "TemplHeader.h"extern template class foo<int>();int main() {
    foo<int> test;
    return 0;}

我知道将所有这些放在一个头文件中是好的,但如果我们在多个文件中实例化具有相同参数的模板,那么我们会得到多个相同的定义,编译器会将它们全部删除(除了一个)以避免错误。我该怎么用extern template?我们可以只将它用于类,还是可以将它用于函数?

此外,图1和图2可以扩展为模板位于单个头文件中的解决方案。在这种情况下,我们需要使用extern template关键字来避免多个相同的瞬时。这仅适用于课程或功能吗?


慕哥6287543
浏览 1255回答 3
3回答

12345678_0001

当您知道它将在其他地方实例化时,您应该只使用extern template强制编译器不实例化模板。它用于减少编译时间和目标文件大小。例如://&nbsp;header.htemplate<typename&nbsp;T>void&nbsp;ReallyBigFunction(){ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Body}//&nbsp;source1.cpp#include&nbsp;"header.h"void&nbsp;something1(){ &nbsp;&nbsp;&nbsp;&nbsp;ReallyBigFunction<int>();}//&nbsp;source2.cpp#include&nbsp;"header.h"void&nbsp;something2(){ &nbsp;&nbsp;&nbsp;&nbsp;ReallyBigFunction<int>();}这将导致以下目标文件:source1.o&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;something1() &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;ReallyBigFunction<int>()&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Compiled&nbsp;first&nbsp;timesource2.o&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;something2() &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;ReallyBigFunction<int>()&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Compiled&nbsp;second&nbsp;time如果两个文件都链接在一起,void ReallyBigFunction<int>()则会丢弃一个文件,从而导致浪费的编译时间和目标文件大小。为了不浪费编译时间和目标文件大小,有一个extern关键字使编译器无法编译模板函数。当且仅当您知道它在其他地方使用相同的二进制文件时,您应该使用它。更改source2.cpp到://&nbsp;source2.cpp#include&nbsp;"header.h"extern&nbsp;template&nbsp;void&nbsp;ReallyBigFunction<int>();void&nbsp;something2(){ &nbsp;&nbsp;&nbsp;&nbsp;ReallyBigFunction<int>();}将导致以下目标文件:source1.o&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;something1() &nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;ReallyBigFunction<int>()&nbsp;//&nbsp;compiled&nbsp;just&nbsp;one&nbsp;timesource2.o&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;something2() &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;No&nbsp;ReallyBigFunction<int>&nbsp;here&nbsp;because&nbsp;of&nbsp;the&nbsp;extern当这两者都链接在一起时,第二个目标文件将只使用第一个目标文件中的符号。不需要丢弃,也不需要浪费编译时间和目标文件大小。这应该仅在项目中使用,例如在多次使用模板时vector<int>,您应该extern在除一个源文件之外的所有文件中使用。这也适用于类和函数作为一个,甚至模板成员函数。

陪伴而非守候

模板的已知问题是代码膨胀,这是在调用类模板特化的每个模块中生成类定义的结果。为了防止这种情况,从C ++ 0x开始,可以在类模板特化之前使用关键字extern#include <MyClass> extern template class CMyClass<int>;模板类的显式实例应仅在单个转换单元中发生,最好是具有模板定义的转换单元(MyClass.cpp)template&nbsp;class&nbsp;CMyClass<int>;template&nbsp;class&nbsp;CMyClass<float>;
随时随地看视频慕课网APP
我要回答