C++ Templates L03 - Iterator 10 – Iterator.

Slides:



Advertisements
Similar presentations
C++ Templates. What is a template? Templates are type-generic versions of functions and/or classes Template functions and template classes can be used.
Advertisements

STL Standard Template Library ● Good reference book: – The C++ Standard Library ● A Tutorial and Reference ● by Nicolai M. Josuttis ● 1999 – Addison Wesley.
C++ Programming Part 2 Michael Griffiths Corporate Information and Computing Services The University of Sheffield
Prof. amr Goneid, AUC1 CSCE 110 PROGRAMMING FUNDAMENTALS WITH C++ Prof. Amr Goneid AUC Part 15. Dictionaries (1): A Key Table Class.
CSE 332: C++ template examples Today: Using Class and Function Templates Two examples –Function template for printing different types –Class template for.
CSE 332: C++ pointers, arrays, and references Overview of Pointers and References Often need to refer to another object –Without making a copy of the object.
CSE 332: C++ templates and generic programming II Review: Concepts and Models Templates impose requirements on type parameters –Types that are plugged.
Motivation for Generic Programming in C++
CS212: Object Oriented Analysis and Design
“Generic Programming” ECE 297
C++ Lesson 1.
Andy Wang Object Oriented Programming in C++ COP 3330
Concepts of Programming Languages
Programming with ANSI C ++
C++ Templates.
Generic Algorithms (TIC++V2:C6)
Lecture 7-2 : STL Iterators
Motivation and Overview
Chapter 14 Templates C++ How to Program, 8/e
CS3340 – OOP and C++ L. Grewe.
Standard Template Library (STL)
Sorting Algorithms.
Friday, January 26, 2018 Announcements… For Today… For Next Time…
Generic Programming Techniques in C++
Monday, March 19, 2018 Announcements… For Today… For Next Time…
Starting Out with C++ Early Objects Eighth Edition
Tuesday, February 20, 2018 Announcements… For Today… 4+ For Next Time…
Templates in C++.
The C++ Algorithm Libraries
Friday, February 16, 2018 Announcements… For Today… 4.5-, pgs. 252
Monday, April 2, 2018 Announcements… For Today… For Next Time…
Prof. Michael Neary Lecture 7: The STL Prof. Michael Neary
Chapter 9 – Sets and Maps 9.1 Associative Container
18 – Sequential Containers
Templates ACKNOWLEDGEMENT: THE SLIDES ARE PREPARED FROM SLIDES PROVIDED BY NANCY M. AMATO AND JORY DENNY.
10 – Iterators C++ Templates 4.6 The Iterator pgs
2.5 Reasoning about Programs: Assertions and Loop Invariants
Lecture 7-2 : STL Iterators
ADT Implementations: Templates and Standard Containers
Lab 04 – Linked List.
Today’s Learning Objective
3.3 Abstract Classes, Assignment, and Casting in a Hierarchy
Lab 03 - Iterator.
C++ STL Vector Container
15 – Sequential Containers
More About Data Types & Functions
14 – Sequential Containers
CMSC 202 Lesson 22 Templates I.
Chapter 9 One-Dimensional Arrays
Andy Wang Object Oriented Programming in C++ COP 3330
Abstraction: Generic Programming, pt. 2
Why Use Namespaces? Classes encapsulate behavior (methods) and state (member data) behind an interface Structs are similar, but with state accessible Classes.
Engineering Problem Solving with C++, Etter
Lecture 8 : Intro. to STL (Standard Template Library)
Standard Template Library (STL)
C++ Templates L03 - Iterator 10 – Iterator.
C++ Templates CSE 333 Summer 2018
Lecture 8-2 : STL Iterators and Algorithms
Parasol Lab, Texas A&M University
C++ Templates L03 - Iterator 10 – Iterator.
Templates I CMSC 202.
Lab4 problems More about templates Some STL
Standard Template Library
Lesson 25 Miscellaneous Topics
C++ Templates CSE 333 Winter 2019
An Introduction to STL.
14 – Sequential Containers
Lab 03 – Linked List.
Lab 04 - Iterator.
C++ Templates L04 - Iterator 10 – Iterator.
Presentation transcript:

C++ Templates L03 - Iterator 10 – Iterator

Attendance Quiz #12 Program Correctness

Tip #10: Standard Integer typedefs Iterators The actual size of integer types varies by implementation. The standard only requires size relations between the data types (i.e., a long long is not smaller than long, which is not smaller than int, which is not smaller than short.) As char's size is always the minimum supported data type, no other data types (except bit-fields) can be smaller. The following pre-processor macros are defined in the header file <stdint.h>: signed unsigned Description int8_t uint8_t Integer type with a width of exactly 8, 16, 32, or 64 bits. For signed types, negative values are represented using 2's complement. No padding bits. int16_t uint16_t int32_t uint32_t int64_t uint64_t std::size_t Largest unsigned integer type; the size of any object in bytes; widely used in the standard library to represent sizes, lengths, and counts.

Strings Are Really Templates C++ Templates Strings Are Really Templates

Template Classes and Functions Iterators C++ templates use "Instantiation-style polymorphism". A template is literally a template; a class template is not a class, it's a recipe for creating a class using template parameters. Class and function functionality can be adapted to more than one type or class without repeating the entire code for each type. template <typename T> class MyPair { private: T values [2]; public: MyPair (T first, T second) values[0]=first; values[1]=second; } }; MyPair<int> myInts(115, 36); MyPair<double> myFloats(3.0, 2.18); template <typename int> int GetMax(int a, int b) { return (a > b ? a : b); } int x,y; GetMax<int>(x, y); template <typename myType> myType GetMax(myType a, myType b) { return (a > b ? a : b); } T is the template parameter name instead of myType because it is shorter and in fact is a very common template parameter name. But you can use any identifier you like.

Lab 03 - Iterator

Array Container Access Iterators By Index #include <iostream> using namespace std; int main() { int dog[] = { 1, 2, 3, 4 }; int* dptr = dog; for (size_t i = 0; i < 4; ++i) cout << *dptr++ << endl; } return 0; By Pointer #include <iostream> using namespace std; int main() { int dog[] = { 1, 2, 3, 4 }; for (size_t i = 0; i < 4; ++i) cout << dog[i] << endl; } return 0;

 Other Containers #include <iostream> #include <vector> Iterators #include <iostream> #include <vector> using namespace std; int main() { vector<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); for (size_t i = 0; i < myArray.size(); ++i) cout << myArray[i] << endl; } return 0; #include <iostream> #include <list> using namespace std; int main() { list<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); for (size_t i = 0; i < myArray.size(); ++i) cout << myArray[i] << endl; } return 0; 

Why Use an Iterator? When avoiding iterators: Assumes your container has index ([]), at, and increment (++,--)operators. Assumes container elements can be randomly accessed, are contiguous, and same size (true for vector but not for many other containers.) Requires many versions of common algorithms (ie., sort, reverse, etc.) Iterators bring you closer to container independence. You're not making assumptions about random-access ability, storage format, or efficiency of operations such as size(). You only need to know that the container has iterator capabilities. Iterators enhance your code further with standard algorithms. Depending on what it is you're trying to achieve, you may elect to use std::for_each(), std::transform(), std::sort() and so on. By using a standard algorithm rather than an explicit loop you're avoiding re-inventing the wheel. Your code is likely to be more efficient (given the right algorithm is chosen), correct and reusable.

The STL Iterator Approach Iterators #include <iostream> #include <list> using namespace std; int main() { list<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); list<int>::iterator iter = myArray.begin(); while (iter != myArray.end()) cout << *iter << " "; ++iter; } return 0; #include <iostream> #include <vector> using namespace std; int main() { vector<int> myArray; myArray.push_back(1); myArray.push_back(2); myArray.push_back(3); myArray.push_back(4); vector<int>::iterator iter = myArray.begin(); while (iter != myArray.end()) cout << *iter << " "; ++iter; } return 0; iter "points" to first element in myArray. myArray.end() "points" after the last element in myArray. Dereference iter to access myArray element.

Iterator Lab Iterators The concept of an iterator is fundamental to understanding the C++ Standard Template Library (STL). Iterators provide access to data stored in container classes (e.g. vector, map, list, etc.) Your Iterator lab implements a C++ array container class that uses an iterator to access the array elements. Your container supplies begin() and end() functions. Your iterator object overloads the not equal ("!="), dereference ("*"), and pre-increment ("++") operators. Use an iterator to sequentially access elements of the associated array class. Read integer values from a file into the array class. Instantiate an iterator using the begin() function and then use the iterator to iterate thru the array values until the iterator equals the iterator returned by the end() function.

Nested Class MyArray Iterator Iterators template<typename T> { private: // MyArray data public: MyArray(const size_t maxSize) { ... } void push_back(T item) { ... } std::string toString() const { ... } friend std::ostream& operator<< (std::ostream& os, const MyArray<T>& myArray) {…}; }; MyArray Iterator class Iterator { private: // Iterator data and private functions public: Iterator(T* array, size_t size, size_t index) { ... } bool operator!= (const Iterator& other) const { ... } // not-equal Iterator& operator++ () { ... } // pre-increment ++ T& operator*() const { ... } // dereference std::string toString() const { ... } friend std::ostream& operator<< (std::ostream& os, const Iterator& iter) {…} }; Iterator begin() { ... } // pointer to first element Iterator end() { ... } // pointer AFTER last element

main Open I/O Streams Read / push_back integer into numbers container. Iterators int main(int argc, char * argv[]) { VS_MEM_CHECK; MyArray<int> numbers(MAX_ARRAY_SIZE); ifstream in(argv[1]); std::ostream& out = (argc < 3) ? std::cout : *(new std::ofstream(argv[2]); out << endl << endl; int i; while (in >> i) numbers.push_back(i); out << numbers << endl << endl; out << "SEQUENTIAL" << endl; MyArray<int>::Iterator iter = numbers.begin(); out << "iter: " << iter << endl; for (; iter != numbers.end(); ++iter) out << *iter << " "; return 0; } Open I/O Streams Read / push_back integer into numbers container. Instantiate Iterator Use friend insertion operator to examine Iterator Output number's contents using dereferencing operator Loop until iter and numbers.end() are equal

Output of Iterator Lab myArray: 1 2 3 4 5 6 7 8 9 10 Iterators myArray: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ITERATORS: begin(): size=20 index=0 end(): size=20 index=20 SEQUENTIAL: PRIME: 2 3 5 7 11 13 17 19 COMPOSITE: 1 4 6 8 9 10 12 14 15 16 18 20 FIBONACCI: 3 = 1 + 2

You may freely use the code in any way you deem useful. ****Disclaimer**** The following code examples are flawed and incomplete, but demonstrate how an iterator class might be implemented. You may freely use the code in any way you deem useful.

Step 1 – int Array Class Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; class MyArray { private: size_t size_; int* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (int*)malloc(maxSize * sizeof(int)); } void push_back(int item) { array_[size_++] = item; } }; int main(int argc, char * argv[]) { MyArray numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); cout << numbers << endl; return 0; } Be sure to use a destructor to free array! string toString() const { stringstream out; out << "myArray"; for (size_t i = 0; i < size_; ++i) out << ((i % 10) ? " " : "\n") << array_[i]; return out.str(); } friend std::ostream& operator<< (ostream& os, const MyArray<T>& myArray) os << myArray.toString(); return os; Remember, every class needs a toString and a Friend!

Step 2 – Template Class Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; template<typename T> class MyArray { private: size_t size_; T* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (T*)malloc(maxSize * sizeof(T)); } void push_back(T item) { array_[size_++] = item; } }; int main(int argc, char * argv[]) { MyArray<int> numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); cout << numbers << endl; return 0; } Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types, allowing a function or class to work on many different data types without being rewritten for each one. There are three kinds of templates: function templates, class templates and, since C++14, variable templates.

Step 3 – Add a Nested Iterator Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; template<typename T> class MyArray { private: size_t size_; T* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (T*)malloc(maxSize * sizeof(T)); } void push_back(T item) { array_[size_++] = item; } class Iterator size_t index_; Iterator(T* a, size_t s) : array_(a), index_(s) { ... } T& operator[](size_t i) const { return array_[i]; } }; Iterator begin() { return MyArray<T>::Iterator(array_, 0); } Iterator end() { return MyArray<T>::Iterator(array_, size_); } int main(int argc, char * argv[]) { MyArray<int> numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); MyArray<int>::Iterator iter = numbers.begin(); for (size_t i = 0; i < 4; ++i) cout << iter[i] << ' '; cout << endl << endl; return 0; } MyArray Iterator Nested classes can access all members of the parent via a reference/pointer.

Step 4 – Add Functionality Iterators #include <iostream> #include <string> #include <sstream> #define MAX_ARRAY_SIZE 1000 using namespace std; template<typename T> class MyArray { private: size_t size_; T* array_; public: MyArray(size_t maxSize) : size_(0) { array_ = (T*)malloc(maxSize * sizeof(T)); } void push_back(T item) { array_[size_++] = item; } class Iterator size_t index_; Iterator(T* a, size_t s) : array_(a), index_(s) { ... } T& operator[](size_t i) const { return array_[index_]; } T& operator*() const { ... } Iterator& operator++() { ... } }; Iterator begin() { return MyArray<T>::Iterator(array_, 0); } Iterator end() { return MyArray<T>::Iterator(array_, size_); } int main(int argc, char * argv[]) { MyArray<int> numbers(MAX_ARRAY_SIZE); numbers.push_back(1); numbers.push_back(2); numbers.push_back(3); numbers.push_back(4); MyArray<int>::Iterator iter = numbers.begin(); for (size_t i = 0; i < 4; ++i, ++iter) cout << *iter << ' ‘; cout << endl << endl; return 0; } Add dereference (*) and pre-increment (++) operators.