templates “generic programming” ece 297. 2 templates a way to write code once that works for...

36
Templates “Generic Programming” ECE 297

Upload: aron-mclaughlin

Post on 17-Jan-2016

214 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

Templates

“Generic Programming”

ECE 297

Page 2: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

2

Templates

• A way to write code once that works for many different types of variables– float, int, char, string, List, Vector, …

• Reference: Problem Solving in C++ by Savitch, Chapter 17

Page 3: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

Template Functions

Page 4: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

4

Types & Functions

• All parameters and local variables in a function must have a type

void swap_val (int &a, int &b){ int temp; temp = a; a = b; b = temp;}

void swap_val (double &a, double &b){ double temp; temp = a; a = b; b = temp;}

OK.Function overloading

Page 5: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

5

Function Templates

• Allow you to write “abstract algorithms”– Work for many types

template<class VariableType>void swap_val (VariableType &a, VariableType &b){ VariableType temp; temp = a; a = b; b = temp;}

“template prefix”defines a type parameter

Can use that “type parameter”instead of a regular typeIn the function

Page 6: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

6

Using a Function Templatetemplate<class VariableType>void swap_val (VariableType &a, VariableType &b){ VariableType temp; temp = a; a = b; b = temp;}

int main () { int i1 = 5, i2 = 10; swap_val (i1, i2); // Compiler will create swap_val<int>

float f1 = 1e6, f2 = 2e6; swap_val (f1, f2); // Compiler will create swap_val<float>}

Template definition must come before template use

Page 7: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

7

Using a Function Template

#include “swap_val.h”int main () { int i1 = 5, i2 = 10; swap_val (i1, i2); // swap_val<int> created

float f1 = 1e6, f2 = 2e6; swap_val (f1, f2); // swap_val<float> created}

template<class VariableType>void swap_val (VariableType &a, VariableType &b){ VariableType temp; temp = a; a = b; b = temp;}

main.cpp

swap_val.h

Page 8: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

8

Restrictions on Swap

swap_val (int, int); swap_val (char, char);swap_val (List, List);swap_val (int, float);

Works for any one type that has proper (deep copy) operator=

template<class VariableType>void swap_val (VariableType &a, VariableType &b){ VariableType temp; temp = a; a = b; b = temp;}

Page 9: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

9

Generic Minimumtemplate<class VariableType>VariableType minimum (VariableType a, VariableType b){ if (a < b) return (a); else return (b);}

minimum (int, int);minimum (float, float); minimum (int[20], int[20]);minimum (List, List);minimum (string, string);

• Works for any type that defines operator< (reasonably)

Page 10: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

Template Classes

Page 11: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

14

Template Classes

• Can make templated (type-generic) classes– Member functions– Member data

• Most useful for container classes– Classes that implement basic data structures– List, Vector, Tree (Map), …

Page 12: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

15

Example: Pair of Data

• Often useful to store two pieces of data together– key, value in ECE 244 lab5 (binary tree for DNS) used together– string name, int ip (244 lab 5)– Could want: string name, string data– or int key, float data– …

• Make a class that can store two arbitrary pieces of data– first (any type)– second (any type)

Page 13: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

16

Generic Pair Classtemplate<class Tfirst, class Tsecond>class MyPair {public: MyPair (Tfirst _first, Tsecond _second); void setFirst (Tfirst _first); void setSecond (Tsecond _second); Tfirst getFirst (); Tsecond getSecond ();

private: Tfirst first; Tsecond second;};

In MyPair.h

Page 14: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

17

Generic Pair Class#include “MyPair.h”

int main () { MyPair<int,float> pair1(1, 2.5); cout << pair1.getFirst() << “ “ << pair1.getSecond(); ...

int first = 1float second = 2.5

pair1

In main.cpp

Creates a variable named pair1class (type) is MyPair<int, float>

Page 15: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

18

Generic Pair Class#include “MyPair.h”int main () { MyPair<int,float> pair1(1, 2.5); cout << pair1.getFirst() << “ “ << pair1.getSecond();

MyPair<string,double> tscore ("Your test score", 7.5); cout << tscore.getFirst() << " " << tscore.getSecond() << endl; tscore.setFirst ("Revised test score"); tscore.setSecond (9.5); cout << tscore.getFirst() << " " << tscore.getSecond() << endl;}

string first = “Your test score”double second = 7.5

tscore

In main.cpp

Creates a variable named tscoreclass (type) is MyPair<string, double>

Page 16: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

19

Generic Pair Class#include “MyPair.h”int main () { MyPair<int,float> pair1(1, 2.5); cout << pair1.getFirst() << “ “ << pair1.getSecond();

MyPair<string,double> tscore ("Your test score", 7.5); cout << tscore.getFirst() << " " << tscore.getSecond() << endl; tscore.setFirst ("Revised test score"); tscore.setSecond (9.5); cout << tscore.getFirst() << " " << tscore.getSecond() << endl;}

1 2.5Your test score 7.5Revised test score 9.5

Program output

In main.cpp

Page 17: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

22

Writing Templates

• Write code for a specific type first– Debug, test

• Convert to template– Can get complex / subtle syntax errors

Page 18: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

STL: Generic Algorithms

Using the Standard Template Libraries

Page 19: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

24

STL

• Writing templates fairly hard• Using templates easy & productive• Standard Template Library

– Fast, well-tested implementations of useful algorithms and data structures

Page 20: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

25

STL References

Basic Reference: “Problem Solving in C++” by Savitch, Chapter 18

Detailed reference: cplusplus.com

Really nitty gritty details: “C++ Primer” by Lippman, Lajoie and Moo

Page 21: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

26

STL

• Writing templates fairly hard• Using templates easy & productive• Standard Template Library

– Fast, well-tested implementations of useful algorithms and data structures

Page 22: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

27

STL: Generic Algorithms

#include <algorithm>using namespace std;

int main ( ) { double x = 1.1, y = 1.2; double z = max (x, y); int j = 2, k = 3; int i = max (j, k); z = max (i, x); z = max (x, 2); z = max (x, 2.0); }

main.cpp

// Won’t compile// Won’t compile

// OK! max (double, double)

Useful algorithms that work with many types in <algorithm>template<class T>T max (T a, T b) { if (a < b) return (b); else return (a);}

<algorithm>

// OK max (int, int)

Page 23: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

28

STL: Generic Algorithms

Also in <algorithm>: min (), sort ()• Work for any one type that defines < and assignment

(operator=)

and lots more – see cplusplus.com• But I only use the very basic ones

Page 24: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

STL Container Classes

Page 25: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

30

STL: Container Classes

• Most useful part of STL – Data structures that just “contain” some other data

type / class– E.g. vector, linked list, binary tree of some type

• Can use to store any type of data (templated)– Avoids a lot of repetitive coding of linked lists, binary

trees, etc.

Page 26: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

31

Vector• Example motivation:

– Want to read integers from cin to an array until EOF> 1 -20 3 31 55 <Ctrl+D>

– Then pass the array on to the rest of the program to process, print, examine, …

– Problem: how big an array should we allocate?int *array = new int[??];

– Don’t know until after the input is read!– Could code up a linked list, load it, count elements,

then allocate array, copy data from linked list, delete linked list

Page 27: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

32

Vector

• Wouldn’t it be great to have something just like an array that could grow as needed?

#include <vector>#include <iostream>using namespace std;

vector<int> get_input ( ) { vector<int> vec; // vector of ints, initially empty int val; cin >> val; while ( !cin.fail() ) { vec.push_back (val); // Add new value to end of vector cin >> val; } return (vec); // Return the whole vector}

main.cpp

Page 28: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

33

Vector: Can Use Like Array#include <vector>#include <iostream>using namespace std;

. . .

int main () { vector<int> in_vals; in_vals = get_input (); for (int i = 0; i < in_vals.size(); i++) cout << in_vals[i] << “ “;

cout << endl;

for (int i = in_vals.size() – 1; i >= 0; i--) cout << in_vals[i] << “ “;}

main.cpp

vectors know how many elements they contain. Valid data from index 0 to size()-1

Fast, O(1), random access to any entry

How would I print out the vector in reverse order?

Input: 1 -20 3 31 55 <Ctrl+D>Output: 1 -20 3 31 55 55 31 3 -20 1

Page 29: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

34

Slightly Cleaner Version

int main () { vector<int> in_vals; in_vals = get_input (); for (int i = 0; i < in_vals.size(); i++) cout << in_vals[i] << “ “;}

Compiler will give a type mismatch warning (.size() is unsigned int). Harmless, but I prefer to have no

warnings.

for (int i = 0; i < (int) in_vals.size(); i++) cout << in_vals[i] << “ “;

Will make warning go away

for (vector<int>::size_type i = 0; i < in_vals.size(); i++) cout << in_vals[i] << “ “;

C++ purist’s way i now unsigned int watch out for >= 0 tests

Page 30: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

35

How Does It Work?

Input:

vector<int> get_input ( ) { vector<int> vec; // vector of ints, initially empty int val; cin >> val; while ( !cin.fail() ) { vec.push_back (val); // Add new value to end of vector cin >> val; } return (vec); // Return the whole vector}

int *arrayint sizeint capacity

1

1 -20

2

1 -20

3 311 -20

1 -20 3 31 55

481123450

3 31 55

vec

Page 31: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

36

Vector: Key Properties

• Efficient to add elements at end (push_back)– Because when there isn’t enough space it

grows the storage quite a bit (usually 2x)– Means even for a large number N of

push_back(), we get only a few array copies– O(1) on average

• Efficient random access to data– Because internally the vector stores the data

in an array operator[ ] can be fast– O(1)

Page 32: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

37

Handy Constructors

#include <vector>using namespace std;

int main () { vector<int> vec1; // default constructor: size = 0 vector<int> vec2(10); // size = 10, but values unknown vector<int> vec3(10,-1); // size = 10, all values -1}

Page 33: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

38

Assignment & Destruction

#include <vector>using namespace std;

int main () { int *a = new int[10]; int *b = new int[10]; vector<int> v1(10), v2(10); a[0] = 2; v1[0] = 2; . . . a = b; // OK? v1 = v2; // OK? delete[] a; delete[] b; delete v1; // Should I? }

No! Shallow copyYes! Proper deep copy defined in <vector>

No! <vector> defines a destructor; cleans up its internal array

Page 34: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

39

operator[]

#include <vector>using namespace std;

int main () { vector<int> v1; v1.push_back(-3);

v1[0] = -2; // OK? v1[1] = -2; // OK? v1.push_back(-3); v1[1] = -2; // OK?}

Yes, entry 0 existsNo, can’t create values with [ ]Yes, can create values with push_back()Yes, entry 1 exists now

Really bad out of bounds array access and memory corruption (maybe seg fault, maybe worse!)• Most compilers have an option to make vector check the [ ] index value is

between 0 and size()-1 and print an error (g++ -D_GLIBCXX_DEBUG)• Slows program down we have turned this on only for the debug

configuration of your milestone1 NetBeans project

Page 35: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

40

Shrinking a vector

#include <vector>using namespace std;

int main () { vector<int> v1; v1.push_back(1); v1.push_back(2);

for (int i = 0; i < in_vals.size(); i++) cout << in_vals[i] << “ “;

v1.pop_back(); // Removes one entry from end of vector for (int i = 0; i < in_vals.size(); i++) cout << in_vals[i] << “ “;}

Output: 1 2

Output: 1

Page 36: Templates “Generic Programming” ECE 297. 2 Templates A way to write code once that works for many different types of variables –float, int, char, string,

41

Vectors should be familiar

• vector<char>• almost same as <string>

– Difference: string defines some extra utility functions– Otherwise a string really is a vector<char>

• Full reference on vector member functions at http://www.cplusplus.com/reference/vector/vector/