Ru-Brd |
The inclusion model ensures that all the needed templates are instantiated . This happens because the C++ compilation system automatically generates those instantiations as they are needed. The C++ standard also offers a construct to instantiate templates manually: the explicit instantiation directive . 6.2.1 Example of Explicit InstantiationTo illustrate manual instantiation, let's revisit our original example that leads to a linker error (see page 62). To avoid this error we add the following file to our program: // basics/myfirstinst.cpp #include "myfirst.cpp" // explicitly instantiate print_typeof() for type double template void print_typeof<double>(double const&); The explicit instantiation directive consists of the keyword template followed by the fully substituted declaration of the entity we want to instantiate. In our example, we do this with an ordinary function, but it could be a member function or a static data member. For example: // explicitly instantiate a constructor of MyClass<> for int template MyClass<int>::MyClass(); // explicitly instantiate a function template max() for int template int const& max (int const&, int const&); You can also explicitly instantiate a class template, which is short for requesting the instantiation of all its instantiatable members. This excludes members that were previously specialized as well as those that were already instantiated: // explicitly instantiate class Stack<> for int : template class Stack<int>; // explicitly instantiate some member functions of Stack<> for strings: template Stack<std::string>::Stack(); template void Stack<std::string>::push(std::string const&); template std::string Stack<std::string>::top(); // ERROR: can't explicitly instantiate a member function of a // class that was itself explicitly instantiated: template Stack<int>::Stack(); There should be, at most, one explicit instantiation of each distinct entity in a program. In other words, you could explicitly instantiate both print_typeof<int> and print_typeof<double> , but each directive should appear only once in a program. Not following this rule usually results in linker errors that report duplicate definitions of the instantiated entities. Manual instantiation has a clear disadvantage : We must carefully keep track of which entities to instantiate. For large projects this quickly becomes an excessive burden; hence we do not recommend it. We have worked on several projects that initially underestimated this burden , and we came to regret our decision as the code matured. However, explicit instantiation also has a few advantages because the instantiation can be tuned to the needs of the program. Clearly, the overhead of large headers is avoided. The source code of template definition can be kept hidden, but then no additional instantiations can be created by a client program. Finally, for some applications it can be useful to control the exact location (that is, the object file) of a template instance. With automatic instantiation, this may not be possible (see Chapter 10 for details). 6.2.2 Combining the Inclusion Model and Explicit InstantiationTo keep the decision open whether to use the inclusion model or explicit instantiation, we can provide the declaration and the definition of templates in two different files. It is common practice to have both files named as header files (using an extension ordinarily used for files that are intended to be #include d), and it is probably wise to stick to this convention. (Thus, myfirst.cpp of our motivating example becomes myfirstdef.hpp , with preprocessor guards around the code inserted.) Figure 6.1 demonstrates this for a Stack<> class template. Figure 6.1. Separation of template declaration and definition
Now if we want to use the inclusion model, we can simply include the definition header file stackdef.hpp . Alternatively, if we want to instantiate the templates explicitly, we can include the declaration header stack.hpp and provide a dot-C file with the necessary explicit instantiation directives (see Figure 6.2). Figure 6.2. Explicit instantiation with two template header files
|
Ru-Brd |