The templates have the particularity that both the declaration and the implementation must be always in a header file.
Why?
Basically because the compiler, when encountering a template, does absolutely nothing ... it does not generate any code. It is expected to find uses of said template to generate the specializations that are required.
But why?
We will agree to say that a template could soon be specialized with a int
than with a class that in turn contains 20 vectors and 200 variables, right? And it is easy to see that the size that occupies a int
is going to be quite lower than the size of the class. Consequently, the code generated for each specialization can be completely different.
If, taking into account the above, we force the compiler to generate specializations when encountering the declaration of the template ... What specializations should you create? All? Even the type you still do not know about? It's something unreal and that would only serve to create insultingly large executables.
What happens then is that the compiler writes down the templates that it finds but does nothing with them until they are not used ... at that moment it creates only and exclusively the specializations that are used in the code .
Compilation unit
We are going to make a small paragraph to explain a detail that is important in the face of what comes next.
If you have ever tried to compile manually, has not it caught your attention that the compiler can pass all the implementation files at once and that, however, it is necessary to use #include
? Put another way ... if the compiler has already passed all the cpp ... What's the point of the headers?
The process of generating an executable in C ++ consists of 2 steps:
In the compilation process the compiler will process each cpp individually. For this, it loads the cpp and launches a utility called preprocessor. This process is responsible for interpreting the #include
, #define
and others. When a #include
is found, it replaces it with the contents of the file it refers to .... if this file has other #include
nested the process will be repeated again and again until there is not a single #include
for processing. That is, a cpp consists of the file itself and of all the headers to which it refers either directly or indirectly ... and that is all the information that the compiler has to carry out its work. This set of files is called the compilation unit.
After the compilation process, the linker is launched. His job is to take the object code files that were generated during the compilation to merge them into a binary.
Going back to templates
Well, to understand the theme of the templates you have to take into account these three points:
- The compiler does nothing with the templates until it finds uses of them
- To compile a template you need to know its implementation
- The compiler only has the information contained in the compilation unit (code referenced by
#include
)
With these requirements on the table it is easy to understand why the code of the templates should travel together. If the template is separated, the compiler will not have the template implementation at its disposal and will not know how to generate the corresponding code.
Errors in the code
If, for readability, convenience, whatever the reason, you decide to put on the one hand the declaration of the template and, on the other, its implementation (always in the same file), you have to keep in mind that you must indicate that the functions belong to a template:
template<class T>
vector_t<T>::vector_t()
{
data_=NULL;
sz_=0;
}
And why should you do this?
They are the rules of the language. It is also a way to differentiate the original template of a specialization:
template<class T>
class vector_t
{
// ...
};
// Especializacion explicita para el tipo int
template<>
class vector_t<int>
{
// ...
};
// Plantilla original
template<class T>
vector_t<T>::vector_t()
{
data_=NULL;
sz_=0;
}
// Codigo de la especializacion a int
template<>
vector_t<int>::vector_t()
{
// ...
}