Controlling
instantiation
At
times it is useful to explicitly instantiate a template; that is, to tell the
compiler to lay down the code for a specific version of that template even
though you’re not creating an object at that point. To do this, you reuse
the
template
keyword as follows:
template class Bobbin<thread>;
template void sort<char>(char*[]);
Here’s
a version of the
Sorted.cpp
example that explicitly instantiates a template before using it:
//: C16:Generate.cpp
// Explicit instantiation
#include <iostream>
#include "Sorted.h"
#include "Integer.h"
using namespace std;
// Explicit instantiation:
template class Sorted<Integer>;
int main() {
Sorted<Integer> is;
Urand<47> rand1;
for(int k = 0; k < 15; k++)
is.add(new Integer(rand1()));
for(int l = 0; l < is.count(); l++)
cout << *is[l] << endl;
} ///:~ In
this example, the explicit instantiation doesn’t really accomplish
anything; the program would work the same without it. Explicit instantiation is
only for special cases where extra control is needed.
Template
specialization
The
Sorted
vector only works with objects of user-defined types. It won’t
instantiate properly to sort an array of
char*,
for example. To create a special version you write the instantiation yourself
as if the compiler had gone through and substituted your type(s) for the
template argument(s). But you put your own code in the function bodies of the
specialization. Here’s an example that shows a
char*
for the
Sorted
vector:
//: C16:Special.cpp
// Note -- this core dumps at least two compilers
// Template specialization
// A special sort for char*
#include <iostream>
#include "Sorted.h"
using namespace std;
// Specialize the class template:
template<> // Essential for specialization
class Sorted<char> : public TStash<char> {
void bubblesort();
public:
int add(char* element) {
TStash<char>::add(element);
bubblesort();
return 0; // Sort moves the element
}
};
void Sorted<char>::bubblesort() {
for(int i = count(); i > 0; i--)
for(int j = 1; j < i; j++)
if(strcmp(storage[j], storage[j-1]) < 0) {
// Swap the two elements:
char* t = storage[j-1];
storage[j-1] = storage[j];
storage[j] = t;
}
}
char* words[] = {
"is", "running", "big", "dog", "a",
};
const int wsz = sizeof words/sizeof *words;
int main() {
Sorted<char> sc;
for(int k = 0; k < wsz; k++)
sc.add(words[k]);
for(int l = 0; l < sc.count(); l++)
cout << sc[l] << endl;
} ///:~ In
the
bubblesort( )
you can see that
strcmp( )
is used instead of
>.
Explicit
specification of template functions
Taking
the address of a generated template function
I
am indebted to Nathan Myers for this example.
//: C19:TemplateFunctionAddress.cpp {O}
// Taking the address of a function generated
// from a template.
template <typename T> void f(T*) {}
void h(void (*pf)(int*)) {}
template <class T>
void i(void (*pf)(T*)) {}
int main() {
// Full type exposition:
h(&f<int>);
// Type induction:
h(&f);
// Full type exposition:
i<int>(&f<int>);
// Type inductions:
i(&f<int>);
i<int>(&f);
} ///:~
Type induction in template functions
As a simple but very useful example, consider the following: //: :arraySize.h // Uses template type induction to discover // the size of an array #ifndef ARRAYSIZE_H #define ARRAYSIZE_H template<typename T, int size> int asz(T (&)[size]) { return size; } #endif // ARRAYSIZE_H ///:~ This
actually figures out the size of an array as a compile-time constant value,
without using any
sizeof( )
operations! Thus you can have a much more succinct way to calculate the size of
an array at compile time:
//: C19:ArraySize.cpp
// The return value of the template function
// asz() is a compile-time constant
#include <iostream>
#include "../arraySize.h"
using namespace std;
int main() {
int a[12], b[20];
const int sz1 = asz(a);
const int sz2 = asz(b);
int c[sz1], d[sz2];
} ///:~ Of
course, just making a variable of a built-in type a
const
does not guarantee it’s actually a compile-time constant, but if
it’s used to define the size of an array (as it is in the last line of
main( )),
then it
must
be a compile-time constant.
Go to CodeGuru.com
Contact: webmaster@codeguru.com
© Copyright 1997-1999 CodeGuru