![]() |
Reference documentation for deal.II version 9.6.0
|
Instantiation of complex class and function templates is expensive both in terms of compile time and disk space. Therefore, we try to separate declaration and implementation of templates as far as possible, and make sure that implementations are read by the compiler only when necessary.
Template classes in deal.II
can be grouped into three categories, depending on the number of probable different instantiations. These three groups are discussed in the following.
These are the classes having template parameters with very predictable values. The typical prototype is
Here, we have a small number of instantiations (dim = 1,2,3
) known at the time of design of the library. Therefore, member functions of this class are defined in a .cc
file in the source directory and we instantiate the template for these known values explicitly in the source file.
From an application viewpoint, all you actually get to see then is the declaration of the template. Actual instantiations of member functions happens inside the library and is done when you compile the library, not when you compile your application code.
For these classes, adding instantiations for new parameters involves changing the library. However, this is rarely needed, of course, unless you are not content with computing only in 1d, 2d, or 3d.
If the template parameter is dim
, the available instances are for dim=1,2,3
, if there is no other information.
There are other cases of classes (not depending on the spatial dimension) for which only a certain, small number of template arguments is supported and explicit instantiations are provided in the library. In particular, this includes all the linear algebra classes that are templatized on the type of the scalar underlying stored values: we only support double
, float
, and in some cases std::complex<double>
and std::complex<float>
.
These are class templates usually having a small number of instantiations, but additional instantiations may be necessary. Therefore, a set of instantiations for the most likely parameters is provided precompiled in the libraries, but the implementation of the templates are provided in a special header file so that it is accessible in case someone wants to instantiate it for an unforeseen argument.
Typical examples for this would be some of the linear algebra classes that take a vector type as template argument. They would be instantiated within the library for Vector<double>
, Vector<float>
, BlockVector<double>
, and BlockVector<float>
, for example. However, they may also be used with other vector types, such as long double
and std::complex<long double>
, as long as they satisfy certain interfaces, including vector types that are not part of the library but possibly defined in an application program. In such a case, applications can instantiate these templates by hand as described in the next section.
Choose one of your source files to provide the required instantiations. Say that you want the class template XXXX
, defined in the header file xxxx.h
, instantiated with the template parameter long double
. Then, your file should contain the lines
Like with the classes in section Known and fixed number of instantiations, the instances provided in the library are often listed in the documentation of that class in a form similar to this:
Template Instantiations: some (<p1>a,b,c<p2>)
These are the classes, where no reasonable predetermined set of instances exists. Therefore, all member definitions are included in the header file and are instantiated wherever needed. An example would be the SmartPointer class template that can be used with virtually any template argument.