Using extern pattern (C ++ 11)

Figure 1: Function Templates

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; } 

Is it correct to use an extern template , or am I using this keyword only for class templates, as shown in Figure 2?

Figure 2: Class Templates

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; } 

I know that it’s good to place all this in one header file, but if we create templates with the same parameters in several files, we will get several identical definitions, and the compiler will delete them all (except for one) to avoid an error. How to use extern template ? Can we use it only for classes, or can we use it for functions too?

In addition, fig. 1 and fig. 2 can be expanded to a solution in which templates are in a single header file. In this case, we need to use the extern template keyword to avoid several identical settings. Is it only for classes or functions?

+95
c ++ c ++ 11 templates extern
Nov 15 2018-11-11T00:
source share
4 answers

You must use the extern template to prevent the compiler from creating an instance of the template when you know that it will be created somewhere else. It is used to reduce compilation time and object file size.

For example:

 // 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>(); } 

This will result in the following object files:

 source1.o void something1() void ReallyBigFunction<int>() // Compiled first time source2.o void something2() void ReallyBigFunction<int>() // Compiled second time 

If both files are connected to each other, one void ReallyBigFunction<int>() will be discarded, which will lead to lost compilation time and the size of the object.

In order not to waste compilation time and the size of the object file, the extern keyword exists, which forces the compiler not to compile the template function. You should use this if and only if you know that it is used in the same binary somewhere else.

Change source2.cpp to:

 // source2.cpp #include "header.h" extern template void ReallyBigFunction<int>(); void something2() { ReallyBigFunction<int>(); } 

As a result, the following object files appear:

 source1.o void something1() void ReallyBigFunction<int>() // compiled just one time source2.o void something2() // No ReallyBigFunction<int> here because of the extern 

When both of them are connected to each other, the second object file will simply use the symbol from the first object file. There is no need to discard and not waste time collecting and the size of the object file.

This should be used only in the project, for example, if you use a template of type vector<int> several times, you should use extern in all but one source file.

This also applies to classes and functions as one and even functions of template members.

+153
Nov 15 2018-11-11T00:
source share

Wikipedia has a better description

In C ++ 03, the compiler must create an instance of a template whenever a fully-defined template is encountered in a translation unit. If a template is created with the same types in many translation units, this can significantly increase compilation time. It is impossible to prevent this in C ++ 03, so C ++ 11 introduced extern template declarations similar to extern data declarations.

C ++ 03 has this syntax to force the compiler to instantiate a template:

  template class std::vector<MyClass>; 

C ++ 11 now provides this syntax:

  extern template class std::vector<MyClass>; 

which tells the compiler not to instantiate the template in this translation unit.

Warning: nonstandard extension used...

Microsoft VC ++ has been using a non-standard version of this function for several years (in C ++ 03). The compiler warns about this in order to prevent portability problems with the code that is needed to compile on different compilers.

See the example on the linked page page to see how it works in much the same way. You can expect the message to disappear with future versions of MSVC, with the exception, of course, of using other non-standard compiler extensions at the same time.

+41
Nov 15 2018-11-11T00:
source share

A known problem with templates is code bloat, which is the result of generating a class definition in each module, which causes the class template to specialize. To prevent this, starting with C ++ 0x, you can use the extern keyword before specializing the class template.

#include <MyClass> extern template class CMyClass<int>;

An explicit instance of a template class should occur in only one translation unit, preferably with a template definition (MyClass.cpp).

 template class CMyClass<int>; template class CMyClass<float>; 
+4
Oct 23 '16 at 18:42
source share

If you used extern for functions before, the exact same philosophy applies to templates. if not, then if extern for simple functions can help. Alternatively, you might want to put extern (s) in the header file and include the header when you need it.

0
Jan 19 '15 at 10:16
source share



All Articles