The concept of templates is basic to the Math.h++ library, and so we begin here. A template is a class declaration parameterized on a type. It is a prescription for how a particular kind of collection should behave. For example, RWMathVec<T> is a template that describes such things as how to index an element, how long it is, how to resize it, and so on. The template establishes a framework for a type you can specify later.
The vector, matrice, and array classes are the collection classes of Math.h++. All of these basic classes are templatized.
Here's how these template classes work. Let's say you request a vector of a particular type, perhaps a vector of doubles such as RWMathVec<double>. The compiler goes back to the template declaration and fills it in for the type double. You get the same result as if you had handwritten a class VectorOfDoubles, but you don't have to do the writing. Instead, the compiler automatically generates the logical equivalent of the specified class.
>Obviously, templates provide enormous benefits. They save time, provide flexibility in using datatypes, and encourage source code reuse. This brings us to the one disadvantage of templates: it is the source code that is reused, not the object code. A declaration for RWMathVec<double> is compiled separately from RWMathVec<int>. This means that the two declarations generate different object code for the two classes, which can bloat the executable.
To some extent, this is unavoidable. For example, if you derive your own class from an RWMathVec <T>, thus forcing it to be parameterized on T, the compiler builds a separate class and object code for each instantiated type T. To save code, it is better to recognize points of commonality that do not depend on the actual type, factor them out, and put them into a separate type-independent class which can be compiled once.
We have followed our own advice in Math.h++; for example, vector length is maintained in the class RWVecView, a base class of RWMathVec. RWVecView is not templatized, nor are any of its base classes. We reduce the code bloat by putting only type-dependent code in the RWMathVec<T>, RWGenMat<T>, and RWMathArray<T> classes, and abstracting the rest to nontemplatized base classes.
>Sometimes a template with a particular type does not follow general template behavior. For example, let's say you implement a templatized function:
template<class T> int LessThan(T a, T b) {return a<b;}
If you later call this function with complex arguments, you get a compiler error. For almost all built-in types, however, the LessThan function does work properly, so you could specialize the LessThan function for the complex type as follows:
int LessThan(DComplex a, DComplex b) {return abs(a)<abs(b);}
In all cases except DComplex, the original LessThan function is called, but if two DComplex arguments are given, the specialization is used.
In some cases, specialization can be a powerful tool. For example, we can use specializations of a helper class rw_numeric_traits to modify the behavior of certain mathematical operations, depending on type. (See Section 2.2.1, "Defining a New Numeric Type.")
Specializations are handled differently from compiler to compiler, and with different degrees of sophistication. For this reason, we keep the number of specializations in Math.h++ to a minimum.
>©Copyright 1999, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.