可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Figure 1: function templates
TemplHeader.h
template void f();
TemplCpp.cpp
template void f(){ //... } //explicit instantation template void f();
Main.cpp
#include "TemplHeader.h" extern template void f(); //is this correct? int main() { f(); return 0; }
Is this the correct way to use extern template
, or do I use this keyword only for class templates as in Figure 2?
Figure 2: class templates
TemplHeader.h
template class foo { T f(); };
TemplCpp.cpp
template void foo::f() { //... } //explicit instantation template class foo;
Main.cpp
#include "TemplHeader.h" extern template class foo(); int main() { foo test; return 0; }
I know it is good to put all of this in one header file, but if we instantiate templates with the same parameters in multiple files, then we got multiple same definitions and the compiler will remove them all (except one) to avoid errors. How do I use extern template
? Can we use it only for classes, or can we use it for functions too?
Also, Figure 1 and Figure 2 may be expanded to a solution where templates are in a single header file . In that case, we need to use the extern template
keyword to avoid multiple same instantations. Is this only for classes or functions too?
回答1:
You should only use extern template
to force the compiler to not instantiate a template when you know that it will be instantiated somewhere else. It is used to reduce compile time and object file size.
For example:
// header.h template void ReallyBigFunction() { // Body } // source1.cpp #include "header.h" void something1() { ReallyBigFunction(); } // source2.cpp #include "header.h" void something2() { ReallyBigFunction(); }
This will result in the following object files:
source1.o void something1() void ReallyBigFunction() // Compiled first time source2.o void something2() void ReallyBigFunction() // Compiled second time
If both files are linked together, one void ReallyBigFunction()
will be discarded, resulting in wasted compile time and object file size.
To not waste compile time and object file size, there is an extern
keyword which makes the compiler not compile a template function. You should use this if and only if you know it is used in the same binary somewhere else.
Changing source2.cpp
to:
// source2.cpp #include "header.h" extern template void ReallyBigFunction(); void something2() { ReallyBigFunction(); }
Will result in the following object files:
source1.o void something1() void ReallyBigFunction() // compiled just one time source2.o void something2() // No ReallyBigFunction here because of the extern
When both of these will be linked together, the second object file will just use the symbol from the first object file. No need for discard and no wasted compile time and object file size.
This should only be used within a project, like in times when you use a template like vector
multiple times, you should use extern
in all but one source file.
This also applies to classes and function as one, and even template member functions.
回答2:
Wikipedia has the best description
In C++03, the compiler must instantiate a template whenever a fully specified template is encountered in a translation unit. If the template is instantiated with the same types in many translation units, this can dramatically increase compile times. There is no way to prevent this in C++03, so C++11 introduced extern template declarations, analogous to extern data declarations.
C++03 has this syntax to oblige the compiler to instantiate a template:
template class std::vector;
C++11 now provides this syntax:
extern template class std::vector;
which tells the compiler not to instantiate the template in this translation unit.
The warning: nonstandard extension used...
Microsoft VC++ used to have a non-standard version of this feature for some years already (in C++03). The compiler warns about that to prevent portability issues with code that needed to compile on different compilers as well.
Look at the sample in the linked page to see that it works roughly the same way. You can expect the message to go away with future versions of MSVC, except of course when using other non-standard compiler extensions at the same time.
回答3:
The known problem with the templates is code bloating, which is consequence of generating the class definition in each and every module which invokes the class template specialization. To prevent this, starting with C++0x, one could use the keyword extern in front of the class template specialization
#include extern class CMyClass;
The explicit instantion of the template class should happen only in a single translation unit, preferable the one with template definition (MyClass.cpp)
template class CMyClass; template class CMyClass;
回答4:
If you have used extern for functions before, exactly same philosophy is followed for templates. if not, going though extern for simple functions may help. Also, you may want to put the extern(s) in header file and include the header when you need it.