Templates and Iterators - Stanford University

98
Templates and Iterators Ali Malik [email protected]

Transcript of Templates and Iterators - Stanford University

Page 2: Templates and Iterators - Stanford University

Game Plan

Recap

Iterator Wrapup

auto and Range Based for

Templates

Iterators (pt. II)

Page 3: Templates and Iterators - Stanford University

Recap

Page 4: Templates and Iterators - Stanford University

Useful abstraction for “associating” a key with a value.

std::mapmap<string, int> directory; // name -> phone number

std::setset<string> dict; // does it contains a word?

Associative Containers

Page 5: Templates and Iterators - Stanford University

IteratorsLet’s try and get a mental model of iterators:

Say we have a std::set<int> mySet

12

34

1 2 3 4

Iterators let us view a non-linear collection in a linear manner.

Page 6: Templates and Iterators - Stanford University

int numOccurences(vector<int>& cont, int elemToCount) { int counter = 0; vector<int>::iterator iter; for(iter = cont.begin(); iter != cont.end(); ++iter) { if(*iter == elemToCount) ++counter; } return counter;}

A standard interface to iterate through any collection.

Iterators

Page 7: Templates and Iterators - Stanford University

Example:

map<int, int> m;

map<int, int>::iterator i = m.begin();

map<int, int>::iterator end = m.end();

while(i != end) {

cout << (*i).first << (*i).second << endl;

++i;

}

Map Iterators

Page 8: Templates and Iterators - Stanford University

Wrapping Up Iterators

Page 9: Templates and Iterators - Stanford University

auto

Page 10: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

auto

Page 11: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

autoWhere might you use this?

Page 12: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

autoWhere might you use this?

Page 13: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto

Page 14: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto How can we clean this up?

Page 15: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto

Use an alias for the collection type!

How can we clean this up?

Page 16: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

using NGramMap = map<deque<string>, vector<string>>;map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto

Use an alias for the collection type!

How can we clean this up?

Page 17: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

using NGramMap = map<deque<string>, vector<string>>;map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto

Use an alias for the collection type!

How can we clean this up?

Page 18: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

auto How can we clean this up?

using NGramMap = map<deque<string>, vector<string>>;NGramMap myMap;for(NGramMap::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

Use an alias for the collection type!

Page 19: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

auto How can we clean this up?

using NGramMap = map<deque<string>, vector<string>>;NGramMap myMap;for(NGramMap::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

Page 20: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto How can we clean this up better?

Page 21: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto How can we clean this up better?

The auto keyword!

Page 22: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(map<deque<string>, vector<string>>::iterator iter =

myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto How can we clean this up better?

The auto keyword!

Page 23: Templates and Iterators - Stanford University

Writing iterator types can be unsightly.

Consider a map of deque of strings to vector of strings:

map<deque<string>, vector<string>> myMap;for(auto iter = myMap.begin(); iter != myMap.end(); ++iter) {

doSomething(*(iter).first, *(iter).second);}

auto How can we clean this up better?

The auto keyword!

Page 24: Templates and Iterators - Stanford University

auto is a C++11 feature that uses type deduction.

Asks the compiler to figure out the type for you.

When to use it?

● Use it whenever the type is obvious (e.g iterators)

● In places where only the compiler knows the type (yes these exist)

auto

Page 25: Templates and Iterators - Stanford University

A range based for loop is (more or less) a shorthand for iterator code:

Range Based for Loop

map<string, int> myMap;for(auto iter = myMap.begin(); iter != myMap. end(); ++iter) { auto thing = *iter; doSomething(thing.first, thing.second);}

map<string, int> myMap;for(auto thing : myMap) { doSomething(thing.first, thing.second);}

Page 26: Templates and Iterators - Stanford University

A range based for loop is (more or less) a shorthand for iterator code:

Range Based for Loop

Page 27: Templates and Iterators - Stanford University

Templates

Page 28: Templates and Iterators - Stanford University

The Problem

Page 29: Templates and Iterators - Stanford University

Let’s write a simple function to find the minimum of two ints.

int min(int a, int b) {return (a < b) ? a : b;

}

Minimum Function

min(3,5); // 3

min(13,8); // 8

min(1.9, 3.7); // 1?

Page 30: Templates and Iterators - Stanford University

min(3,5); // 3

min(13,8); // 8

min(1.9, 3.7); // 1?

Let’s write a simple function to find the minimum of two ints.

int min(int a, int b) {return (a < b) ? a : b;

}

Minimum Function

Page 31: Templates and Iterators - Stanford University

double min_double(double a, double b) {return (a < b) ? a : b;

}

int min_int(int a, int b) {return (a < b) ? a : b;

}

A classic C type solution would be to write two functions with different names:

Need more min

Page 32: Templates and Iterators - Stanford University

int min_int(int a, int b) {return (a < b) ? a : b;

}

And… more

double min_double(double a, double b) {return (a < b) ? a : b;

}size_t min_sizet(size_t a, size_t b) {

return (a < b) ? a : b;}float min_float(float a, float b) {

return (a < b) ? a : b;}

uh...

...

char min_ch(char a, char b) {return (a < b) ? a : b;

}

Page 33: Templates and Iterators - Stanford University

And… more

double min_double(double a, double b) {return (a < b) ? a : b;

}

int min_int(int a, int b) {return (a < b) ? a : b;

}

size_t min_sizet(size_t a, size_t b) {return (a < b) ? a : b;

}float min_float(float a, float b) {

return (a < b) ? a : b;}char min_ch(char a, char b) {

return (a < b) ? a : b;}

Page 34: Templates and Iterators - Stanford University

Multiple copies of essentially the same function.

The Problem

Page 35: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it.

Page 36: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it.

Every time you want to add a new type, you need to add a new function.

Page 37: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it

Every time you want to add a new type, you need to add a new function.

If you edit the function slightly, you need to edit it in each version manually

Page 38: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it

Every time you want to add a new type, you need to add a new function.

If you edit the function slightly, you need to edit it in each version manually

Page 39: Templates and Iterators - Stanford University

When the method is called, the compiler infers which version you mean based on the type of your parameters.

int min(int a, int b) {return (a < b) ? a : b;

}

In C++, function overloading lets us have multiple functions with the same name but different parameters.

Overloaded Functions

double min(double a, double b) {return (a < b) ? a : b;

}

Page 40: Templates and Iterators - Stanford University

min(3,5); // (int, int) version

min(1.9, 3.7); // (double, double) version

min(3.14, 17); // uhh.. (double, int) version?

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

Overloaded Functions

Page 41: Templates and Iterators - Stanford University

min(3,5); // (int, int) version

min(1.9, 3.7); // (double, double) version

min(3.14, 17); // uhh.. (double, int) version?

Overloaded Functions

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

Page 42: Templates and Iterators - Stanford University

min(3,5); // (int, int) version

min(1.9, 3.7); // (double, double) version

min(3.14, 17); // uhh.. (double, int) version?

min(3.14, static_cast<double>(17)); // (double, double) version!

Overloaded Functions

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

Page 43: Templates and Iterators - Stanford University

Overloaded Functions

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

min(3,5); // (int, int) version

min(1.9, 3.7); // (double, double) version

min(3.14, 17); // uhh.. (double, int) version?

min(3.14, static_cast<double>(17)); // (double, double) version!

Lesson: Be explicit!

Page 44: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it

Every time you want to add a new type, you need to add a new function.

If you edit the function slightly, you need to edit it in each version manually

Page 45: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it

Every time you want to add a new type, you need to add a new function.

If you edit the function slightly, you need to edit it in each version manually

Page 46: Templates and Iterators - Stanford University

The Problems

Multiple copies of essentially the same function.

You need to write the type name whenever you use it

Every time you want to add a new type, you need to add a new function.

If you edit the function slightly, you need to edit it in each version manually

Page 47: Templates and Iterators - Stanford University

What really is different in the code?

Page 48: Templates and Iterators - Stanford University

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

size_t min(size_t a, size_t b) {return (a < b) ? a : b;

}float min(float a, float b) {

return (a < b) ? a : b;}char min(char a, char b) {

return (a < b) ? a : b;}

Page 49: Templates and Iterators - Stanford University

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

size_t min(size_t a, size_t b) {return (a < b) ? a : b;

}float min(float a, float b) {

return (a < b) ? a : b;}char min(char a, char b) {

return (a < b) ? a : b;}

Page 50: Templates and Iterators - Stanford University

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

size_t min(size_t a, size_t b) {return (a < b) ? a : b;

}float min(float a, float b) {

return (a < b) ? a : b;}char min(char a, char b) {

return (a < b) ? a : b;}

Page 51: Templates and Iterators - Stanford University

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

size_t min(size_t a, size_t b) {return (a < b) ? a : b;

}float min(float a, float b) {

return (a < b) ? a : b;}char min(char a, char b) {

return (a < b) ? a : b;}

Page 52: Templates and Iterators - Stanford University

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

size_t min(size_t a, size_t b) {return (a < b) ? a : b;

}float min(float a, float b) {

return (a < b) ? a : b;}char min(char a, char b) {

return (a < b) ? a : b;}

The type is the only difference!

Page 53: Templates and Iterators - Stanford University

double min(double a, double b) {return (a < b) ? a : b;

}

int min(int a, int b) {return (a < b) ? a : b;

}

size_t min(size_t a, size_t b) {return (a < b) ? a : b;

}float min(float a, float b) {

return (a < b) ? a : b;}char min(char a, char b) {

return (a < b) ? a : b;}

The type is the only difference!

If only there were a better way

Page 54: Templates and Iterators - Stanford University

The Solution

Page 55: Templates and Iterators - Stanford University

Templates

Templates are a blueprint of a function that let you use the same function for a variety of types:

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}

Page 56: Templates and Iterators - Stanford University

TemplatesThink about how we wrote all our min functions.

We had a set of rules (a blueprint), and the only thing we did to make different versions was to change the type.

int min(int a, int b) {return (a < b) ? a : b;

}

Page 57: Templates and Iterators - Stanford University

TemplatesThink about how we wrote all our min functions.

We had a set of rules (a blueprint), and the only thing we did to make different versions was to change the type.

int min(int a, int b) {return (a < b) ? a : b;

}

Page 58: Templates and Iterators - Stanford University

TemplatesThink about how we wrote all our min functions.

We had a set of rules (a blueprint), and the only thing we did to make different versions was to change the type.

double min(double a, double b) {return (a < b) ? a : b;

}

Page 59: Templates and Iterators - Stanford University

TemplatesWe can give that blueprint to the compiler in the form of a template function by telling it what specific parts need to get replaced.

Just before the function we specify a template parameter.

int min(int a, int b) {return (a < b) ? a : b;

}

Page 60: Templates and Iterators - Stanford University

TemplatesWe can give that blueprint to the compiler in the form of a template function by telling it what specific parts need to get replaced.

Just before the function we specify a template parameter.

int min(int a, int b) {return (a < b) ? a : b;

}

Let’s make this general.

Page 61: Templates and Iterators - Stanford University

TemplatesWe can give that blueprint to the compiler in the form of a template function by telling it what specific parts need to get replaced.

Just before the function we specify a template parameter.

T min(T a, T b) {return (a < b) ? a : b;

}

Some generic type T.

Page 62: Templates and Iterators - Stanford University

TemplatesWe can give that blueprint to the compiler in the form of a template function by telling it what specific parts need to get replaced.

Just before the function we specify a template parameter.

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}s

Tell compiler T is a generic type.

Page 63: Templates and Iterators - Stanford University

TemplatesWe can give that blueprint to the compiler in the form of a template function by telling it what specific parts need to get replaced.

Just before the function we specify a template parameter.

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}s

Tell compiler T is a generic type.

It will replace the parameter for us!

Page 64: Templates and Iterators - Stanford University

Now we can use the template function just like any other function!

We can indicate the type through angle brackets after the function name:

Using Templates

int a = 3, b = 9;int c = min<int>(a, b);

double a = 3.14, b = 1.59;double c = min<double>(a, b);s

Page 65: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

How does this work?

Page 66: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

How does this work?

Page 67: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

How does this work?

I don’t have a min<int> :(

Page 68: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

I don’t have a min<int> :(

But I know how to make one!

How does this work?

Page 69: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

I don’t have a min<int> :(

But I know how to make one!

How does this work?

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}

Page 70: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

How does this work?

I don’t have a min<int> :(

But I know how to make one!

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}

Template Instantiation

(T = int)

Page 71: Templates and Iterators - Stanford University

int a = 3, b = 9;int c = min<int>(a, b);s

How does this work?

I don’t have a min<int> :(

But I know how to make one!

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}

Template Instantiation

(T = int)int min<int>(int a, int b) {

return (a < b) ? a : b;}

Page 72: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min<int>(a, b);s

Page 73: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min<int>(a, b);s

Page 74: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min(a, b);s

Page 75: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min(a, b); Type inferred

Page 76: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min(a, b); Type inferred

The template parameter name can be anything. I used T but a more descriptive name is usually better.

Page 77: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min(a, b); Type inferred

The template parameter name can be anything. I used T but a more descriptive name is usually better.

template <typename T>T min(T a, T b) {

return (a < b) ? a : b;}

Page 78: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min(a, b);s

Type inferred

The template parameter name can be anything. I used T but a more descriptive name is usually better.

template <typename Type>Type min(Type a, Type b) {

return (a < b) ? a : b;}

Page 79: Templates and Iterators - Stanford University

Templates - AsideYou can usually omit the angle brackets when using the function.

int a = 3, b = 9;int c = min(a, b); Type inferred

The template parameter name can be anything. I used T but a more descriptive name is usually better.

template <typename DataType>DataType min(DataType a, DataType b) {

return (a < b) ? a : b;}

Page 80: Templates and Iterators - Stanford University

Questions?

Page 81: Templates and Iterators - Stanford University

Templates in Action

Let’s do a very realistic example of templates. Could be useful in assignments!

Generic Input(GenInput.pro)

Page 82: Templates and Iterators - Stanford University

When Templates Go Wrong

Any time template instantiation occurs, the compiler will check that all operations used on the templatised type are supported by that type.

“With great power comes great responsibility” - Uncle Ben

Generic Input(GenInput.pro)

Page 83: Templates and Iterators - Stanford University

Errors

../Input/main.cpp:63:19: error: invalid operands to binary expression ('istringstream' (aka 'basic_istringstream<char>') and 'std::__1::vector<int, std::__1::allocator<int> >')converter >> ret;~~~~~~~~~ ^ ~~~../Input/main.cpp:93:27: note: in instantiation of function template specialization 'getInput<std::__1::vector<int, std::__1::allocator<int> > >' requested herevector<int> vec_inp = getInput<vector<int>>("Enter a vector (yolo): ");

The start of the error is usually the most informative. For example, we got:

Invalid operands to binary expression “>>” tells us we are using the stream operator on a type that doesn’t know how to work with them (in this case, vector).

Page 84: Templates and Iterators - Stanford University

Errors

../Input/main.cpp:63:19: error: invalid operands to binary expression ('istringstream' (aka 'basic_istringstream<char>') and 'std::__1::vector<int, std::__1::allocator<int> >')converter >> ret;~~~~~~~~~ ^ ~~~../Input/main.cpp:93:27: note: in instantiation of function template specialization 'getInput<std::__1::vector<int, std::__1::allocator<int> > >' requested herevector<int> vec_inp = getInput<vector<int>>("Enter a vector (yolo): ");

The start of the error is usually the most informative. For example, we got:

Invalid operands to binary expression “>>” tells us we are using the stream operator on a type that doesn’t know how to work with them (in this case, vector).

Page 85: Templates and Iterators - Stanford University

Implicit Interface

What types are valid to use with a templatized function?

Any that satisfy its implicit interface.

Page 86: Templates and Iterators - Stanford University

Implicit Interface

template <typename T>int foo(T input) { int i;

if(input >> i && input.size() > 0) { input.push_back(i); return i; } else { return 5; }}

Page 87: Templates and Iterators - Stanford University

Implicit Interface

template <typename T>int foo(T input) { int i;

if(input >> i && input.size() > 0) { input.push_back(i); return i; } else { return 5; }}

input >> int

Page 88: Templates and Iterators - Stanford University

Implicit Interface

template <typename T>int foo(T input) { int i;

if(input >> i && input.size() > 0) { input.push_back(i); return i; } else { return 5; }}

input >> int

input.size()

Page 89: Templates and Iterators - Stanford University

Implicit Interface

template <typename T>int foo(T input) { int i;

if(input >> i && input.size() > 0) { input.push_back(i); return i; } else { return 5; }}

input >> int

input.size()

input.push_back(int)

Page 90: Templates and Iterators - Stanford University

Implicit Interface

template <typename T>int foo(T input) { int i;

if(input >> i && input.size() > 0) { input.push_back(i); return i; } else { return 5; }}

input >> int

input.size()

input.push_back(int)

Page 91: Templates and Iterators - Stanford University

Implicit Interface

template <typename T>int foo(T input) { int i;

if(input >> i && input.size() > 0) { input.push_back(i); return i; } else { return 5; }}

input >> int

input.size()

input.push_back(int)

Can type T perform these operations?

Page 92: Templates and Iterators - Stanford University

Implicit Interface

Basically, if we replace all instances of T with the actual type we want to use, would it compile?

Page 93: Templates and Iterators - Stanford University

Let’s take a moment

Page 94: Templates and Iterators - Stanford University

Templates ft. Iterators

Page 95: Templates and Iterators - Stanford University

vector<int> v;vector<int>::iterator itr = v.begin();

Every different collection comes equipped with its own type of iterator:

Templates ft. Iterators

vector<double> v;vector<double>::iterator itr = v.begin();

sdeque<int> d;deque<int>::iterator itr = d.begin();

Page 96: Templates and Iterators - Stanford University

The whole point of iterators was to have a standard interface to iterate over data in any container.

But we still had to specify what type of data this iterator was pointing to.

We want to ultimately write generic functions to work with iterators over any sequence.

With templates we can!

Templates ft. Iterators

Page 97: Templates and Iterators - Stanford University

With this newfound power, let’s write our first generic algorithm!

Templates ft. Iterators

Count Occurences(IterAlgorithms.pro)

Page 98: Templates and Iterators - Stanford University

Next TimeAlgorithms