Week 10

1 / 33

# Week 10 - PowerPoint PPT Presentation

Week 10. Hand in Lab 6 Templates Lab 7. Templates. Say you’ve written a function like this: int max(int a, int b) { if (a > b) return a; return b; } But now you need another: max(float x, float y). Repetitive code. Max, min, compare Squaring, cubing, combining

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Week 10' - tracey

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Week 10
• Hand in Lab 6
• Templates
• Lab 7

Kate Gregorywith material from Deitel and Deitel

Templates
• Say you’ve written a function like this:

int max(int a, int b)

{

if (a > b) return a;

return b;

}

• But now you need another:max(float x, float y)

Kate Gregorywith material from Deitel and Deitel

Repetitive code
• Max, min, compare
• Squaring, cubing, combining
• Sorting, normalizing, converting
• The type-safety of C++ makes these work well, but can require a lot of code

Kate Gregorywith material from Deitel and Deitel

You have choices
• Copy and paste
• Error prone
• Hard to ripple changes through if you change the original
• Use #define
• Awful because of side effects
• Dangerous casts

Kate Gregorywith material from Deitel and Deitel

#define macros

#define sq(a) a * a

int x = sq(2);

int y = sq(1+1);

• Expands to 1 + 1 * 1 + 1
• 3!

Kate Gregorywith material from Deitel and Deitel

#define macros

int j=sq(i++);

• Expands to i++ * i++
• i will be incremented twice
• Side effects of macros can be reduced with many extra () but never eliminated
• Macros are not a safe road to genericity

Kate Gregorywith material from Deitel and Deitel

Dangerous casts

void* max(void* a, void* b)

• Cast everything you pass to it and everything you get back
• Must de-reference pointers
• Can’t stop people comparing apples and oranges
• Throwing away the entire type system: and for what? The compiler is your friend.

Kate Gregorywith material from Deitel and Deitel

Template Functions

template<class T>

T biggest(T a, T b)

{

if ( a > b) return a;

return b;

}

• Here T is a placeholder. You can name your placeholders whatever you like

Kate Gregorywith material from Deitel and Deitel

Using a template function

cout << "biggest of 4 and 5 is " << biggest(4,5) << endl;

cout << "biggest of 4.1 and 5.2 is " << biggest(4.1,5.2) << endl;

Kate Gregorywith material from Deitel and Deitel

Using a template function

Holder h1(4);

Holder h2(5);

cout <<

"biggest of h1 and h2 is: " << biggest(h1,h2) << endl;

Kate Gregorywith material from Deitel and Deitel

Templates and Operators
• The biggest function will only work if Holder has overloaded the > operator
• The code using biggest will only work if Holder has overloaded the << operator
• Without operator overloading, one template couldn’t work with both fundamental types (eg int) and user defined types (ie classes).

Kate Gregorywith material from Deitel and Deitel

What happens here?

cout <<

"biggest of Hello and 2 is " << biggest("Hello", 2);

• Compiler error.
• Eg: error C2782: 'T biggest(T,T)' : template parameter 'T' is ambiguous

Kate Gregorywith material from Deitel and Deitel

What happens here?

cout << "biggest of Hello and World is " << biggest("Hello", "World");

cout << "biggest of A and XYZ is " << biggest("A", "XYZ") << endl;

cout << "biggest of ABC and Z is " << biggest("ABC", "Z") << endl;

• The results are actually compiler specific
• Visual C++ 6: second literal string is always “biggest”
• Visual C++.NET: first literal string is always “biggest”
• It’s based on the numerical value of the pointer

Kate Gregorywith material from Deitel and Deitel

More string comparisons

char* Hello1 = "Hello";

char* World = "World";

char* Hello2 = "Hello";

cout << "biggest of Hello1 and World is " << biggest(Hello1,World) << endl;

• World

cout << "biggest of Hello2 and World is " << biggest(Hello2,World) << endl;

• Hello

Kate Gregorywith material from Deitel and Deitel

Providing a Specific Implementation
• What if I wanted biggest to use string length when passed a char* ?

template<> char* biggest(char* a, char* b)

{

if (strlen(a) > strlen(b) )

return a;

return b;

}

Kate Gregorywith material from Deitel and Deitel

Class Templates
• Consider writing an Array class like the one presented earlier in this course
• self-growing when users attempt to set values past the end of the array
• Preventing access before the beginning of the array
• But an Array of What?

Kate Gregorywith material from Deitel and Deitel

More Duplication
• You could write IntArray, FloatArray, StringArray, and so on
• A lot of duplicate work
• Or you could write a generic array that worked with void*
• What would stop people from mixing object types within an array?
• Annoying to cast everything in and out of the array
• Couldn’t put literal values (Eg 3) in the array because you can’t take their address

Kate Gregorywith material from Deitel and Deitel

Solution

template<class C> class Array

{

private:

C* data;

int length;

public:

Array(): data(NULL),length(0) {};

C& operator[](int i);

friend ostream& operator<<(ostream& o, const Array& a);

};

Kate Gregorywith material from Deitel and Deitel

How do you implement the functions?

template<class C> int Array<C>::getlength()

{

return length;

}

Kate Gregorywith material from Deitel and Deitel

How do you implement the functions?

template<class C>

ostream& operator<<(ostream& o, const Array<C>& a)

{

for (int i=0;i<a.length;i++)

{

o << a[i] << “ “;

}

return o;

};

Kate Gregorywith material from Deitel and Deitel

How do you use a template?

Array<int> ai;

ai[0] = 1;

ai[3] = 2;

cout << ai[2] << endl;

cout << ai[5] << endl;

Kate Gregorywith material from Deitel and Deitel

Templates work with classes and fundamental types too

Array<Holder> ah;

ah[0] = h1;

ah[2] = h2;

cout << ah[0] << endl;

cout << ah[1] << endl;

cout << ah[4] << endl;

Kate Gregorywith material from Deitel and Deitel

Templates impose requirements
• In order to work with the Array template, Holder requires:
• Default constructor
• operator= or single-argument constructor
• operator<<
• If you try to instantiate a template object and the class is missing some requirements, you’ll receive a compiler error

Kate Gregorywith material from Deitel and Deitel

Specialized Overrides
• As with function templates, you may need to write a special case for certain types.
• For example the Array template needs to initialize extra elements when it grows. It allocates a “scratch” element for this:

template<class C>

C& Array<C>::operator[](int i)

{ ...

C c;

...

• This only works for objects, not for fundamental types or pointers

Kate Gregorywith material from Deitel and Deitel

Specialized Overrides

template<> int& Array<int>::operator[](int i)

{

. . .

int c=0;

. . .

}

Kate Gregorywith material from Deitel and Deitel

Specialized Overrides

template<> char*& Array<char*>::operator[](int i)

{

. . .

char* c = "";

. . .

}

Kate Gregorywith material from Deitel and Deitel

The Standard Template Library
• Arrays, stacks, linked lists and so on are obvious template choices
• Why should everyone develop them?
• The Standard Template Library offers a variety of “computer science” templates that are likely to be useful in almost every program.
• Most modern compilers come with an implementation of the Standard Template Library

Kate Gregorywith material from Deitel and Deitel

The vector STL Template

#include <vector>

. . .

vector<int> vi;

vi.push_back(1);

vi.push_back(2);

vi.push_back(3.5); // warning

//re truncation

vi.push_back(h1); //error: can't

//convert Holder to int

cout << vi[1] << endl;

Kate Gregorywith material from Deitel and Deitel

Going through the whole vector

for (int i=0;i<vi.size();i++)

cout << vi[i] << " " ;

• What if you want them in a specific order?
• What if you’re using a collection other than vector?
• Not all STL collections provide operator[] access

Kate Gregorywith material from Deitel and Deitel

STL Iteration
• The STL separates container classes (vector, stack, etc) from objects that know how to go through a container
• Iterators can work with a number of different containers
• An iterator “points to” each element in turn
• Not really, but operator* and operator-> are overloaded

Kate Gregorywith material from Deitel and Deitel

Using an Iterator

for (vector<int>::iterator it=vi.begin();

it != vi.end();

it++)

{

cout << *it << " ";

}

Kate Gregorywith material from Deitel and Deitel

For Next class