View
225
Download
0
Embed Size (px)
Citation preview
Example…
What happens if we want to swap a double ? or a string?
For each one, we need different function:void Swap( double& a, double &b )
{
double tmp = a; a = b; b = tmp;
}
void Swap( string& a, string &b )
{
string tmp = a; a = b; b = tmp;
}
Generic Programming
All these versions of Swap are “isomorphic”
// template code for Swap for arbitrary type T
void Swap( T& a, T &b )
{
T tmp = a;
a = b;
b = tmp;
}
Can we somehow tell the compiler to use Swap with any type T?
Templates
The template keyword defines “templates” Piece of code that will be regenerated with
different arguments each time
template<class T> // T is a “type argument”void Swap( T& a, T &b ) {T tmp = a; a = b; b = tmp;
}
Template Instantiation
int main()
{
int a = 2;
int b = 3;
Swap( a, b ); // requires Swap( int&, int& )
}
The compiler encounters Swap( int&, int& )
It instantiates the template Swap with T = int
and compiles the code defined by it
Template Instantiation
Different instantiations of a template can be generated by the same program
See Swap.cpp
Templates & Compilation A template is a declaration The compiler performs syntax checks only When a template is instantiated with specific
arguments, then the generated code is compiled
Implications: Template code has to be visible by the code
that uses it (i.e., appear in .h file) Compilation errors can occur only in a
specific instance (see Swap.cpp)
Another Example…
// Inefficient generic sort…
template< class T >
void
Sort( T* begin, T* end )
{
for( ; begin != end; begin++ )
for( T* q = begin+1; q != end; q++ )
if( *q < *begin )
Swap( *q, *begin );
}
See [Sort.h, TestSort.cpp]
More Complex Case…
Suppose we want to avoid writing operator != for new classes
template <class T>
bool
operator!= (T const& lhs, T const& rhs)
{
return !(lhs == rhs);
}
When is this template used?
More Complex Case…class MyClass {
public:
…
bool operator==(MyClass const & rhs) const;
…
};
…
int a, b;
…
if( a != b ) // uses built in operator!=(int,int)
…
MyClass x,y;
if( x != y ) // uses template with T = MyClass
…
When Templates are Used?
When the compiler encounters…
f( a, b )
…
Search for a function f() with matching type signature
If not found, search for a template function that can be instantiated with matching types
Generic Classes?
Suppose we implement a class StrList that maintains a list of strings See StrList.h and StrList.cpp
The actual code for maintaining the list has nothing to do with the particulars of the string type
Can we have a generic implementation of lists?
Class Templates
template<class T>
class MyList {
…
};
…
MyList<int> intList; // T = int
MyList<string> stringList; // T = string
Class Templates
Code similar to usual code: Add template<…> statement before each
top-level construct Use template argument as type in class
definition
Implementation of methods, somewhat more complex syntax See MyList.h TestMyList.h
Constructing a List
We want to initialize a list from an array We can write a method that receives a
pointer to the array, and a size argumentint array[] = { 1, 2, 3, 4, 5, 6 };
MyList<int> list;
list.copy( array, 6 );
Alternative: use a pointer to initial position and one to the position after the lastlist.copy( array, array+6 );
This form is more flexible (as we shall see)
Constructing a List
// Fancy copy from array
template< class T >
MyList<T>::copy( T const* begin,
T const* end )
{
T const* p;
for( p = begin; p != end; p++ )
pushBack(*p);
}
Pointer Paradigm
Code like:T * p;
for( p = begin; p != end; p++ )
{
// Do something with *p
…
}
Applies to all elements in [begin,end-1] Common in C/C++ programs Can we extend it to other containers?
Iterator
Object that behaves just like a pointer Allows to iterate over elements of a container
Example:MyList<int> L;
…
MyList<int>::iterator i;
for( i = L.begin(); i != L.end(); i++ )
cout << " " << *i << "\n";
Iterators
To emulate pointers, we need: copy constructor operator = (copy) operator == (compare) operator * (access value) operator++ (increment)
MyList<T> iterator
Keep a pointer to a nodeclass iterator {
…
private:
Node m_pointer;
};
Provide encapsulation, since through such an iterator we cannot change the structure of the list
See MyListWithIterators.h
Side Note operator++
In C we can use ++ in two forms: prefix notation ++x
increment x fetch x’s value
postfix notation x++ fetch x’s value increment x
How can we implement both variants?
Operator++
Prefix form:T& T::operator++();
Postfix formT T::operator++(int); // dummy argument!
Note different return types
See MyListWithIterators.h
Initializing a List
We now want to initialize a list from using parts of another list
Something liketemplate< class T >
MyList<T>::copy( iterator begin,
iterator end )
{
iterator p;
for( p = begin; p != end; p++ )
pushBack(*p);
}
Generic Constructor
The code for copying using T* MyList<T>::iterator
are essentially identical on purpose --- iterators mimic pointers
Can we write the code once?
Template within a templatetemplate < class T > class MyList {
…
template< class Iterator >
copy( Iterator begin, Iterator end )
{
for( Iterator p = begin; p != end; p++ )
pushBack(*p);
}
…
};
Copy Method
MyList<T>::copy() can be instantiated with different types pointer to T MyList<T>::iterator Iterators of other data structures that
contain objects of type T
Template Variations
Can receive constant argumentstemplate< class T, int Size = 1024>
class Buffer {
…
private:
T m_values[Size];
};
…
Buffer<char> Buff1;
Buffer<char,1024> Buff2; // same as Buff1
Buffer<int, 256> Buff3;
Template and Types
Buffer is not a type Buffer<char,1024> is a type Buffer<char>, buffer<char,1024> are two
names for the same type Buffer<char,256> is a different type
Class Templates - Recap
Provides support for generic programming Parameters are either types or constants.
Default values can be specified Depends only on the properties it uses from
its parameter types Resulting classes may be very efficient, but
code size may be larger Difficult to write, maintain and debug Class template overloading is impossible
Summary
Alternative mechanism to polymorphism
Write & Debug concrete example (e.g., StringList) before generalizing to a template
Understand iterators and other “helper” classes
Foundation for C++ standard library (STL)