The (not so new anymore) C++11 standard introduced the extern
keyword for templates. Its purpose is to tell the compiler that a template should not be instantiated at the point of usage, but that it will be instantiated in another translation unit (and thus there will be an instantiation available at link time) - at least AFAIK.
Now, even in the pre-C++11 era we used something similar to separate the declaration/definition of template classes from its instantiation in order to speed up compilation, e.g. like so:
point.h: class definition
template <int dim> struct Point {
...
void foo();
...
};
point.cpp: method definitions
#include "point.h"
template <int dim>
void Point<dim>::foo() {
...
}
point_2d.cpp: class instantiation (2D version)
#include "point.cpp"
template struct Point<2>;
point_3d.cpp: class instantiation (3D version)
#include "point.cpp"
template struct Point<3>;
main.cpp: usage of 2D and 3D points
#include "point.h"
int main(int, char**) {
Point<2> p;
p.foo();
}
Now I am wondering:
point.cpp
in main.cpp
and declaring extern template <int dim> struct Point;
?Your approach is a valid C++ code and should work both in C++03 and C++11. It is called explicit instantiation:
template struct Point<2>;
While applying to class templates it explicitly instantiates all members of a class template for some template argument list in the current translation unit. With this approach it is simple to create the libraries of templates for which the set of possible template arguments is known in advance (as in your case when Point
can be 2D and 3D but not 1D, 4D etc.).
In C++11 when you add to explicit instantiation directive keyword extern
:
extern template struct Point<2>;
it becomes a declaration, not a definition. The behavior of such thing is similar to usual extern
keyword for variables. Explicit template instantiation declaration can be used together with explicit instantiation in the following manner:
// point.h
template <int dim> struct Point {
...
void foo();
...
};
extern template struct Point<2>;
extern template struct Point<3>;
#include "point.hpp"
// point.hpp
#include "point.h"
template <int dim>
void Point<dim>::foo() {
...
}
// point.cpp
#include "point.hpp"
template struct Point<2>;
template struct Point<3>;
With such code you achieve the same result as with your one but additionally you allow the users of your code to use Point<1>
, Point<4>
and other specializations of a Point
class template if they want. Without extern template struct Point<2>;
and extern template struct Point<3>;
directives Point
class template would be implicitly instantiated in the users code even for template arguments 2
and 3
that reduces the meaning of explicit instantiation (template struct Point<2>;
and template struct Point<2>;
).