\documentstyle[12pt]{article}
\oddsidemargin 0.25in
\topmargin -0.5in
\textheight 8.5in
\textwidth 6.25in
\newcommand{\doublespace}{
   \renewcommand{\baselinestretch}{1.5}
   \large\normalsize}
\newcommand{\singlespace}{
   \renewcommand{\baselinestretch}{1.0}
   \large\normalsize}
\newcommand{\be}{\begin{equation}}
\newcommand{\ee}{\end{equation}}

\begin{document}
\setcounter{page}{46}

\centerline{\large{\bf LECTURE 5}}

\centerline{\bf Templates}
We have written a simple array class of float variables. 
But suppose we want to have arrays of integers, or doubles, or
something else. It's a pain to write a separate array class
for each new case. Templates make it easy to have arrays of
anything; not just ints, floats, and doubles, but {\it anything}.
In general, templates make it easy to make a family of classes of
closely related objects.
To make a template, write the class for something definite,
like floats. Then turn it into a class template. As an example,
let's do this with our array class.

\begin{verbatim}

#include <iostream.h>
#include "arraytemplate.h"

void main()
  {
    // Create arrays with the desired number of elements
    int n;  
    cin >> n;
    Array<float> x(n);
    Array<int> y(n);

    // Read the data points
    for (int i = 0; i < n; i++) {
        cin >> x[i] >> y[i];
    }

   ...
   }
\end{verbatim}

\centerline{\bf File "arraytemplate.h"}

A class template declaration consists of the keyword {\tt template},
followed by a list of {\it template arguments} enclosed in angular
brackets (\verb2< >2), followed
by a class declaration. These template arguments may be type--arguments
preceded by the keyword {\tt class} and/or numeric arguement declarations.
For example:
\begin{verbatim}
template<class T> class Array;             // Class template declaration

	or
template<class T, int nL> class vector;    // For a vector of length nL.
\end{verbatim}

Let's stick with the first case.
\begin{verbatim}
template<class T> class Array;             // Class template declaration

template<class T>                          // T="type",e.g.,int or float
class Array {
public:

    Array(int n);                          // Create array of n elements
    Array();                               // Create array of 0 elements
    Array(const Array<T>&);                // Copy array
    ~Array();                              // Destroy array
    T& operator[](int i);                  // Subscripting
    int numElts();                         // Number of elements
    Array<T>& operator=(const Array<T>&);   // Array assignment
    Array<T>& operator=(T);                // Scalar assignment 
    void setSize(int n);                   // Change size
private:
    int num_elts;                          // Number of elements
    T* ptr_to_data;                  // Pointer to built-in array of elements

    void copy(const Array<T>& a);          // Copy in elements of a
};
\end{verbatim}
Notice that the declarations of the constructor and destructor
member functions do not include the parameter {\tt T}.

\centerline{\bf Definitions of Template Member Functions}
Notice that member function definitions for class templates
are preceded by the {\tt template} keyword with \verb2<class T>2,
but are otherwise analogous to ordinary member function definitions.

\begin{verbatim}
template<class T>
Array<T>::Array(int n) {
    num_elts = n;
    ptr_to_data = new T[n];
}

template<class T>
Array<T>::Array() {
    num_elts = 0;
    ptr_to_data = 0;
}

template<class T>
Array<T>::Array(const Array<T>& a) {
    num_elts = a.num_elts;
    ptr_to_data = new T[num_elts];
    copy(a); // Copy a's elements
}

template<class T>
void Array<T>::copy(const Array<T>& a) {
    // Copy a's elements into the elements of *this
    T* p = ptr_to_data + num_elts;
    T* q = a.ptr_to_data + num_elts;
    while (p > ptr_to_data) *--p = *--q;
}

template<class T>
Array<T>::~Array() {
    delete [] ptr_to_data;
}

template<class T>
T& Array<T>::operator[](int i) {
    #ifdef CHECKBOUNDS
       if(i < 0 || i > num_elts)
          error("out of bounds");
    #endif
    return ptr_to_data[i];
}

template<class T>
int Array<T>::numElts() {
    return num_elts;
}

template<class T>
Array<T>& Array<T>::operator=(const Array<T>& rhs) {
    if ( ptr_to_data != rhs.ptr_to_data ) {
        setSize( rhs.num_elts );
        copy(rhs);
    }
    return *this;
}

template<class T>
void Array<T>::setSize(int n) {
    if (n != num_elts) {

        delete [] ptr_to_data;    // Delete old elements,
        num_elts = n;             // set new count,
        ptr_to_data = new T[n];   // and allocate new elements

    }
}

template<class T>
Array<T>& Array<T>::operator=(T rhs) {
    T* p = ptr_to_data + num_elts;
    while (p > ptr_to_data) *--p = rhs;
    return *this;
}
\end{verbatim}
We can see from the {\tt main()} program how templates are
instanced.   \verb2Array<float> x(n)2 is an instance of the template.
Here {\tt T} has become {\tt float}.

\centerline{\bf Comments on Templates}
\begin{enumerate}
\item No code is generated for a template. Code is generated after
the template is converted into a concrete class or function. Thus
the {\tt .cc} source file is almost never associated with a template
class. The entire template class definition, including all the
member functions, should be contained in the {\tt .h} include file
so that it can be available for the compiler to expand.

If you do decide to put the template declarations in a {\tt .h}
file and the template definitions in a {\tt .cc} file, then
put \verb2#include "Array.cc"2 at the very bottom of the
{\tt Array.h} file and in the {\tt Array.cc} file, remove
\verb2#include "Array.h"2. Don't try to compile {\tt Array.cc}.
Just compile the rest of the source files, like the file with the
{\tt main} program. The compiler will do the rest. (This works with
g++, but I don't guarantee it for other compilers.)
\item A template class does not consume any memory. But every instance
of a template class does take up memory. 
\item A template class cannot be compiled and checked for errors
until it has been converted into a real class. Thus, a template
class {\tt Array} might compile fine even though it contains
obvious syntax errors. The errors won't appear until a class such 
as \verb2Array<float> x(n)2 is created. Even if an error does appear
when instancing a template class, it does not necessarily mean
the template class has a problem. The problem may be in the 
instance itself.
\end{enumerate} 

\centerline{\bf Const in Classes}

Class objects may be declared {\tt const} in the same way as intrinsic
types. Like an intrinsic object, a user--defined object must be assigned 
a value when it is created. For example, suppose we have defined a 
{\tt class Student} where the constructor just requires the
student's name as an argument ({\tt Student::Student(char* name)}).
Then we could say create a constant object in {\tt main}:
\begin{verbatim}
const Student Michael("Michael");
\end{verbatim}
A {\tt const} object can't be changed
after initialization. The compiler will declare an error if you
try to pass a {\tt const} object to a function that might try to change
the object. One important use of {\tt const} is to prevent bugs
by safeguarding objects that you know shouldn't be changed. Consider
the following example which uses our Array template. Recall that
{\tt strings} are arrays of {\tt char}s.
\begin{verbatim}
    char day0[]="Sunday";
    Array<char>d(7);
    int i;
    for(i=0;i<7;i++)
      d[i] = day0[i];
    const Array<char>Day_zero=d;    //const Array can't be changed after
                                    //declaration. Notice that this
                                    //calls the copy constructor.

    Array<char>aday = Day_zero;     //It's ok to set a nonconst object equal
                                    //to a const one. Calls copy constructor.

    aday[0] = Day_zero[0];          //Get compiler warning.
                                    //Not ok to set a reference to a const
                                    //array element equal to a nonconstant
                                    //reference that might change it.

    int n = Day_zero.numElts();     //Get compiler warning.
\end{verbatim}
The problem is that \verb2Day_zero2 is declared {\tt const}, but
the \verb2operator[]()2 and the function {\tt numElts()} are
not declared {\tt const}. In particular, these functions take
nonconstant arguments, so the compiler is worried that the
functions might change the {\tt const} Array.
So we need to change the definitions. 
\begin{verbatim}
template<class T>                          // T="type",e.g.,int or float
class Array {
public:

    Array(int n);                          // Create array of n elements
    Array();                               // Create array of 0 elements
    Array(const Array<T>&);                // Copy array
    ~Array();                              // Destroy array
    T& operator[](int i);                  // Subscripting
//******************** Note the word "const"*************************
    int numElts() const;                   // Number of elements
    const T& operator[](int i) const;      // Subscripting
//*******************************************************************
    Array<T>& operator=(const Array<T>&);   // Array assignment
    Array<T>& operator=(T);                // Scalar assignment
    void setSize(int n);                   // Change size
private:
    int num_elts;                          // Number of elements
    T* ptr_to_data;                  // Pointer to built-in array of elements

    void copy(const Array<T>& a);          // Copy in elements of a
};
// Function definitions
template<class T>
int Array<T>::numElts() const{
    return num_elts;
}

// New subscript operator, returns const T
template <class T>
const T & Array <T>::operator[](int i) const
   { return ptr_to_data[i]; }


// Old supscript operator, not const
template <class T>
T & Array <T>::operator[] (int i)
   { return ptr_to_data[i]; }

\end{verbatim}

When we put {\tt const} after a function declaration, as in
\begin{verbatim}
   int numElts() const
\end{verbatim}
we don't mean that this function can't change. We mean that this
is a function that can't change the class object that it belongs to.
This is in contrast to a non{\tt const} function which can change 
the object it belongs to. 
You can pass a {\tt const} function
nonconstant arguments, especially since these arguments
often do not refer to \verb2*this2 object. If these arguments are not
to be changed, then declare them {\tt const}:
\begin{verbatim}
     void fn(const Array& A2); 
\end{verbatim} 
When {\tt const} appears in front of a function declaration,
we mean that it returns a {\tt const} value or reference. For example,
the first {\tt const} in
\begin{verbatim}
   const T& operator[](int i) const;
\end{verbatim}
means that the subscripted variable returns a reference to a {\tt const}
object.
The compiler is smart enough to choose between the {\tt const}
and nonconstant operator function: 
\begin{verbatim}
   const T& operator[](int i) const;
    T& operator[](int i); 
\end{verbatim}
It chooses according to whether
the current object is constant or not. This is a case of operator overloading.
You can also overload functions with respect
to the {\tt const}ness of their explicit arguments. Thus, the
following two functions are not ambiguous:
\begin{verbatim}
     void fn(Array& A);       //used for non-const objects
     void fn(const Array& A); //used for const objects
\end{verbatim}

Another solution to our problem is to write
\begin{verbatim}
   T operator[](int i) const;              //does not return a reference
   T & operator[](int i);                  //returns a reference
\end{verbatim}
Notice that \verb2T operator[](int i) const2 does not return a reference.
Rather it returns the value of the {\it i}th element of the array, 
so that the {\it i}th element can't be changed and is kept {\tt const}.
\verb2T & operator[](int i)2 returns a reference that can later be changed.

Why bother with {\tt const}? Because it is a good way to safeguard
your program and keep out bugs. Recall that the external function
\begin{verbatim}
     void fn(Array A);
\end{verbatim}
is safe in that it can't overwrite the Array object because it's
passed a copy of {\tt A}. But suppose {\tt Array A} is maintained
in a large relational database so that making a copy requires a
lot of time and effort. In that case it's easier to pass a reference
to {\tt Array A}, thus enhancing the efficiency of your program.
So you write 
\begin{verbatim}
     void fn(Array& A);
\end{verbatim}
But now there's the danger that {\tt fn()} will overwrite {\tt Array A}.
Even if you think that {\tt fn()} doesn't change {\tt Array A},
when debug time comes, you can't exclude the possibility. So you
write
\begin{verbatim}
     void fn(const Array& A);
\end{verbatim}
So the moral of the story is that you should put in {\tt const}
wherever you can. If you know that the function doesn't change
its argument, add {\tt const} to the end of the declaration.

(By the way, you only put {\tt const} at the end of a declaration
of a function that's a member of a class. It doesn't make sense
to put it at the end of the declaration of an external function.)

\centerline{\bf Template Functions}
We have seen how classes can be made into templates. You can also
have templates for functions that are not members of classes.
For example:
\begin{verbatim}
  #include <iostream.h>

  template <class T>
  T MAX(T num1, T num2)                  //template function
   {
     return (num1 > num2 ? num1 : num2);
   }

  template <class T>
  T SQR(T num)                          //template function
   {
     return (num * num);
   }

  int main()
    {
      float x, y, z1, z2, z3;
      long m;
      cin >> x >> y;
      z1 = MAX(x,y);
      z2 = SQR(x+y); 
      cout << z1 <<" "<< z2 << endl; 
      cin >> m;
      z3 = MAX(m,x);                //won't work, template won't convert 
                                    //argument types
      return 0;
    }
\end{verbatim}
You can also use template functions with user-defined types (classes),
as long as the operators in the template function make sense for the class.
For example if you wanted to use {\tt MAX} with {\tt Student},
the ``less than'' symbol (\verb2<2) would have to be defined in the
class {\tt Student}.

In C one can define macros that act like template functions, but macros
are more error prone. For example if you wrote:
\begin{verbatim}
  #define sqr(x) (x*x)

   func(float x, float y, float z)
    {
      z = sqr(x + y);              //z=x+y*x+y=x+(y*x)+y due to operator 
                                   //precedence
      cout << z << endl;
    }
\end{verbatim}
In addition, macros don't provide type checking.


\end{document}

