Lecture 9: Templates
Lecture 9: Templates
9.1 Class templates
A class template definition looks like any other class definition except it is preceeded by a declaration of dummy arguments. For example:
template<class X, class Y, class Z> class stack {
// ...
};An instance or declaration of this parameterized class is obtained as with other classes except an appended parameter list indicates what types (not necessarily classes) or constants are to be used to substitute for the dummys.
HStack example.
Templates can be thought of as a sophisticated macro facility with quite possibly the same amount of code resulting. Various parameterizations don't necessarily share code with each other.
Non-inline definition of a member function combines both of these syntaxes. For example:
template<class X, class Y, class Z> X& stack<X, Y, Z>::push(Y& y) { ... }
When defining the constructor the suffix can be left off the member name:
template<class X, class Y, class Z> stack<X, Y, Z>::stack(Z& z) { ... }
In general, the class can be referred to without the angular-bracketed parameter list once inside the lexical scope of the definition.
HStack example with additional constant parameter representing stack size.
PtrStack template from the examples. Class PtrType must be a pointer type, otherwise the compiler won't be able to generate template code. The unsafe (PtrType) cast is insulated by the template definition. And that's the total purpose of this wrapper template: to define a type-safe interface to the generic HStack<void *> code. All instances share same code. The template results in no extra code being generated over what would be present without the template. It just allows for more type safety. An example below shows how such type-safe wrappers can be constructed for generic C functions.
If a class template needs to be escaped for a particular type, the code for the class can be written out explicitly treating BinaryTree<char *> (or whatever) like it was any other type. See LTCmp() in sort2.C. Some compilers allow escaping on a member function level.
9.2 Function templates
Definition of a template for a family of functions looks a lot like a class template. There is an important restriction that every template argument (stuff in < ... >) must affect the type of at least one function argument.
This restriction means the compiler can generate the appropriate instance of the template just by looking at the types of the function arguments, so a < ... > suffix on the function identifier (required when instancing class templates) is not used when instancing from function templates.
In overloading resolution, regular (non-templated) functions are looked through first for an exact match. Unlike the case when no templates are extant, no conversions at all are attempted. Then templates are searched for an exact match (again no conversions). If there is still no match, then regular functions are reviewed again with the usual conversion attempts. No match after this is an error. So if a function template needs to be "escaped" for a certain type, the function can just be defined explicitly for that type.
Example: a template for swap()
If the restrictions imposed by the function template are too much, a class with a single static member function can be used instead.
Example: sort2.C, a type-safe wrapper for the ANSI qsort().
0 comments: