A drawback of this approach is obviously that all template source code is visible to the client. If you want to know exactly how your standard library is implemented, all you have to do is inspect the headers in your installation. There is little opportunity for library vendors to hide their implementation strategies. Another noticeable disadvantage of the inclusion model is that header files are much, much larger than they would be if function bodies were compiled separately. This can increase compile times dramatically over traditional compilation models.
To help reduce the large headers required by the inclusion model, C++ offers two (non-exclusive) alternative code organization mechanisms: you can manually instantiate each specialization using
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( )
Here are the files:
//: C05:OurMin.h
#ifndef OURMIN_H
#define OURMIN_H
// The declaration of min
template
#endif ///:~
// OurMin.cpp
#include "OurMin.h"
// The definition of min
template
return (a < b) ? a : b;
}
//: C05:UseMin1.cpp {O}
#include
#include "OurMin.h"
void usemin1() {
std::cout << min(1,2) << std::endl;
} ///:~
//: C05:UseMin2.cpp {O}
#include
#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
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
template const double& min
const double&);
///:~
To manually instantiate a particular template specialization, you precede the specialization’s declaration with the template keyword. That’s it! 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,[77] 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
return (a < b) ? a : b;
}
#endif ///:~
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