Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Explicit instantiation

You can manually direct the compiler to instantiate any template specializations of your choice. When you use this technique, there must be one and only one such directive for each such specialization; otherwise you might get multiple definition errors, just as you would with ordinary, non-inline functions with identical signatures. To illustrate, we first (erroneously) separate the declaration of the min( ) template from earlier in this chapter from its definition, following the normal pattern for ordinary, non-inline functions. The following example consists of five files:

      OurMin.h: contains the declaration of the min( ) function template.

      OurMin.cpp: contains the definition of the min( ) function template.

      UseMin1.cpp: attempts to use an int-instantiation of min( ).

      UseMin2.cpp: attempts to use a double-instantiation of min( ).

      MinMain.cpp: calls usemin1( ) and usemin2( ).

//: C05:OurMin.h
#ifndef OURMIN_H
#define OURMIN_H
// The declaration of min()
template<typename T> const T& min(const T&, const T&);
#endif // OURMIN_H ///:~
 
// OurMin.cpp
#include "OurMin.h"
// The definition of min()
template<typename T> const T& min(const T& a, const T& b) {
return (a < b) ? a : b;
}
 
//: C05:UseMin1.cpp {O}
#include <iostream>
#include "OurMin.h"
void usemin1() {
std::cout << min(1,2) << std::endl;
} ///:~
 
//: C05:UseMin2.cpp {O}
#include <iostream>
#include "OurMin.h"
void usemin2() {
std::cout << min(3.1,4.2) << std::endl;
} ///:~
 
//: C05:MinMain.cpp
//{L} UseMin1 UseMin2 MinInstances
void usemin1();
void usemin2();
 
int main() {
usemin1();
usemin2();
} ///:~
 

When we attempt to build this program, the linker reports unresolved external references for min<int>( ) and min<double>( ). The reason is that when the compiler encounters the calls to specializations of min( ) in UseMin1 and UseMin2, only the declaration of min( ) is visible. Since the definition is not available, the compiler assumes it will come from some other translation unit, and the needed specializations are thus not instantiated at that point, leaving the linker to eventually complain that it cannot find them.

To solve this problem, we will introduce a new file, MinInstances.cpp, that explicitly instantiates the needed specializations of min( ):

//: C05:MinInstances.cpp {O}
#include "OurMin.cpp"
 
// Explicit Instantiations for int and double
template const int& min<int>(const int&, const int&);
template const double& min<double>(const double&,
const double&);
///:~
 

To manually instantiate a particular template specialization, you precede the specialization s declaration with the template keyword. Note that we must include OurMin.cpp, not OurMin.h, here, because the compiler needs the template definition to perform the instantiation. This is the only place where we have to do this in this program,[84] however, since it gives us the unique instantiations of min( ) that we need the declarations alone suffice for the other files. Since we are including OurMin.cpp with the macro preprocessor, we add include guards:

//: C05:OurMin.cpp {O}
#ifndef OURMIN_CPP
#define OURMIN_CPP
#include "OurMin.h"
 
template<typename T> const T& min(const T& a, const T& b) {
return (a < b) ? a : b;
}
#endif // OURMIN_CPP ///:~
 

Now when we compile all the files together into a complete program, the unique instances of min( ) are found, and the program executes correctly, giving the output:

1
3.1
 

You can also manually instantiate classes and static data members. When explicitly instantiating a class, all member functions for the requested specialization are instantiated, except any that may have been explicitly instantiated previously. This is important, as it will render many templates useless when using this mechanism specifically, templates that implement different functionality depending on their parameterization type. Implicit instantiation has the advantage here: only member functions that get called are instantiated.

Explicit instantiation is intended for large projects where a hefty chunk of compilation time can be avoided. Whether you use implicit or explicit instantiation is independent of which template compilation you use. You can use manual instantiation with either the inclusion model or the separation model (discussed in the next section).

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire