图 1:函数模板
TemplHeader.h
template<typename T>
void f();
TemplCpp.cpp
template<typename T>
void f(){
//...
}
//explicit instantation
template 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 instantation
template 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
关键字来避免多个相同的实例化。这也只适用于类或函数吗?
最佳答案
你应该只使用 extern template
当您知道模板将在其他地方实例化时,强制编译器不实例化模板。它用于减少编译时间和目标文件大小。
例如:
// header.h
template<typename T>
void ReallyBigFunction()
{
// Body
}
// source1.cpp
#include "header.h"
void something1()
{
ReallyBigFunction<int>();
}
// source2.cpp
#include "header.h"
void something2()
{
ReallyBigFunction<int>();
}
这将产生以下目标文件:
source1.o
void something1()
void ReallyBigFunction<int>() // Compiled first time
source2.o
void something2()
void ReallyBigFunction<int>() // Compiled second time
如果两个文件链接在一起,一个void ReallyBigFunction<int>()
将被丢弃,导致编译时间和目标文件大小的浪费。
为了不浪费编译时间和目标文件大小,有一个 extern
使编译器不编译模板函数的关键字。 当且仅当您知道它在其他地方的相同二进制文件中使用时,您才应该使用它。
改变 source2.cpp
到:
// source2.cpp
#include "header.h"
extern template void ReallyBigFunction<int>();
void something2()
{
ReallyBigFunction<int>();
}
将产生以下目标文件:
source1.o
void something1()
void ReallyBigFunction<int>() // compiled just one time
source2.o
void something2()
// No ReallyBigFunction<int> here because of the extern
当这两个链接在一起时,第二个目标文件将只使用第一个目标文件中的符号。不需要丢弃,也不会浪费编译时间和目标文件大小。
这应该只在项目中使用,就像在使用 vector<int>
这样的模板时一样。多次,你应该使用 extern
在除一个源文件之外的所有文件中。
这也适用于类和函数作为一个整体,甚至模板成员函数。
关于c++ - 使用外部模板 (C++11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44205599/