Writing Generic Functions Lecture 20 Hartmut Kaiser

Slides:



Advertisements
Similar presentations
Data Structures Using C++ 2E
Advertisements

Exceptions, Templates, And The Standard Template Library (STL) Chapter 16.
Copyright © 2012 Pearson Education, Inc. Chapter 16: Exceptions, Templates, and the Standard Template Library (STL)
C++ How to Program, 7/e © by Pearson Education, Inc. All Rights Reserved.
C++ Sets and Multisets Set containers automatically sort their elements automatically. Multisets allow duplication of elements whereas sets do not. Usually,
Chapter 10.
OOP Etgar 2008 – Recitation 101 Object Oriented Programming Etgar 2008 Recitation 10.
OOP Spring 2007 – Recitation 81 Object Oriented Programming Spring 2007 Recitation 8.
C++ Programming: Program Design Including Data Structures, Second Edition Chapter 22: Standard Template Library (STL)
Starting Out with C++: Early Objects 5/e © 2006 Pearson Education. All Rights Reserved Starting Out with C++: Early Objects 5 th Edition Chapter 16 Exceptions,
CS0007: Introduction to Computer Programming Introduction to Arrays.
The Stack and Queue Types Lecture 10 Hartmut Kaiser
CSE 332: C++ templates and generic programming I Motivation for Generic Programming in C++ We’ve looked at procedural programming –Reuse of code by packaging.
C++ / G4MICE Course Session 3 Introduction to Classes Pointers and References Makefiles Standard Template Library.
Templates and the STL.
CSE 332: Combining STL features Combining STL Features STL has containers, iterators, algorithms, and functors –With several to many different varieties.
CSE 332: C++ Algorithms II From Last Time: Search with Generic Iterators Third generalization: separate iterator type parameter We arrive at the find algorithm.
Organizing Programs and Data 2 Lecture 7 Hartmut Kaiser
C++ How to Program, 8/e © by Pearson Education, Inc. All Rights Reserved. Note: C How to Program, Chapter 22 is a copy of C++ How to Program Chapter.
Data Structures Using C++ 2E
Chapter 9 Defining New Types. Objectives Explore the use of member functions when creating a struct. Introduce some of the concepts behind object-oriented.
© The McGraw-Hill Companies, 2006 Chapter 4 Implementing methods.
CNS  Sequences  vector,deque,list,(string),forward_list  Container Adapters  queue, stack, priority_queue  Associative Containers  set, unordered_set.
CSE 332: C++ Type Programming: Associated Types, Typedefs and Traits A General Look at Type Programming in C++ Associated types (the idea) –Let you associate.
Project 1 Due Date: September 25 th Quiz 4 is due September 28 th Quiz 5 is due October2th 1.
Defining New Types Lecture 21 Hartmut Kaiser
Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Cpt S 122 – Data Structures Standard Template Library (STL)
Copyright © Curt Hill Generic Classes Template Classes or Container Classes.
CSC 211 Data Structures Lecture 13
Working with Batches of Data Lecture 4 Hartmut Kaiser
Chapter 9: Part 2: Vectors + Maps and STL Overview JPC and JWD © 2002 McGraw-Hill, Inc. Modified by S. Sudarshan.
Looping and Counting Lecture 3 Hartmut Kaiser
CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element.
Taking Strings Apart (and putting them together) Lecture 11 Hartmut Kaiser
Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Cpt S 122 – Data Structures Templates.
C++ How to Program, 9/e © by Pearson Education, Inc. All Rights Reserved.
 2003 Prentice Hall, Inc. All rights reserved.m ECE 2552 Dr. Këpuska based on Dr. S. Kozaitis Summer Chapter 15 - Class string and String Stream.
1 CSC241: Object Oriented Programming Lecture No 25.
Overview of C++ Templates
Chapter 3 Working with Batches of Data. Objectives Understand vector class and how it can be used to collect, store and manipulate data. Become familiar.
C++ / G4MICE Course Session 1 - Introduction Edit text files in a UNIX environment. Use the g++ compiler to compile a single C++ file. Understand the C++
Copyright © 2000, Department of Systems and Computer Engineering, Carleton University 1 Introduction An array is a collection of identical boxes.
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 6: User-Defined Functions I.
1 Becoming More Effective with C++ … Day Two Stanley B. Lippman
Using Sequential Containers Lecture 8 Hartmut Kaiser
1 Chapter 3 Lists, Stacks, and Queues Reading: Sections 3.1, 3.2, 3.3, 3.4 Abstract Data Types (ADT) Iterators Implementation of Vector.
CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)
LECTURE LECTURE 17 Templates 19 An abstract recipe for producing concrete code.
Chapter 8 Writing Generic Functions. Objectives Understand the use of generic functions. Learn about the use of templates, their advantages and pitfalls.
1 ENERGY 211 / CME 211 Lecture 7 October 6, 2008.
Chapter 16 Templates Copyright © 2008 Pearson Addison-Wesley. All rights reserved.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Function Templates 16.2.
Unit VI.  C++ templates are a powerful mechanism for code reuse, as they enable the programmer to write code (classes as well as functions) that behaves.
Motivation for Generic Programming in C++
CS212: Object Oriented Analysis and Design
Exceptions, Templates, and the Standard Template Library (STL)
Standard Template Library (STL)
Prof. Michael Neary Lecture 7: The STL Prof. Michael Neary
ADT Implementations: Templates and Standard Containers
Defining New Types Lecture 22 Hartmut Kaiser
Abstraction: Generic Programming, pt. 2
Standard Version of Starting Out with C++, 4th Edition
Lists - I The List ADT.
Lists - I The List ADT.
Exceptions, Templates, and the Standard Template Library (STL)
COP 3330 Object-oriented Programming in C++
Lab4 problems More about templates Some STL
Some Definitions vector, string, deque, and list are standard sequence containers. set, multiset, map, multimap, unordered_set, unordered_multiset, unordered_map.
SPL – PS1 Introduction to C++.
Presentation transcript:

Writing Generic Functions Lecture 20 Hartmut Kaiser

Code Quality 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 2

Programming Principle of the Day Minimize Coupling - Any section of code (code block, function, class, etc.) should minimize the dependencies on other areas of code. This is achieved by using shared variables as little as possible. Low coupling is often a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 3

Abstract So far we have concentrated on the abstractions provided to us by C++ and the Standard library Now we start looking into creating our own abstractions  This lecture talks about generic functions, which are functions with parameter types that we do not know until we call the functions  The next lectures will focus on abstract data types and later on object oriented programming 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 4

Generic Functions For all functions we’ve seen so far we knew the types of its parameters Seems natural, however we have already used (not written) functions which didn’t have that property For instance std::find()  Takes two iterators and a value  Usable for any appropriate type for any container  Implies we do not know types until we use the functions This is called a Generic Function  Key feature of C++ 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 5

Generic Functions What exactly does it mean to have arguments of “any appropriate type”?  How can we know whether it will work for a given set of argument types? Two parts to that answer  Inside C++: the ways a function uses the arguments of unknown type constrains that arguments type  Function does x + y, this implies there is a defined operator + applicable to the types of ‘x’ and ‘y’  Implementation checks whether x + y is defined, and if yes, types of ‘x’ and ‘y’ are ‘appropriate’ 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 6

Generic Functions Two parts to that answer  Outside C++: the way the Standards library constrains the argument types for its functions  Iterators: supports a collection of operations with well defined semantics  Function expecting iterators as arguments will use those in a way relying on the iterator semantics  Writing your own containers implies to write iterators exposing ‘appropriate’ operators and semantics 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 7

Median of Unknown Type Generic functions are implemented using template functions  Single definition for a family of functions (or types) that behave similarly  Types are parameters, relies on knowledge that different types still have common properties and behavior Template functions are written in terms of this common behavior  When function is used a concrete type is known, which allows to compile and link program 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 8

Median of Unknown Type That’s what we’ve used before: double median(vector v) { typedef vector ::size_type vec_sz; vec_sz size = v.size(); if (size == 0) throw domain_error("median of an empty vector"); sort(v.begin(), v.end()); vec_sz mid = size/2; return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid]; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 9

Median of Unknown Type That’s what how it looks like: template T median(vector v) { typedef typename vector ::size_type vec_sz; vec_sz size = v.size(); if (size == 0) throw domain_error("median of an empty vector"); sort(v.begin(), v.end()); vec_sz mid = size/2; return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid]; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 10

Median of Unknown Type For template functions, the type of T is deduced by the compiler when function is used: vector vi; // = { 1, 2, 3, 4 }; median(vi); // instantiates median with T == int vector vd; // = { 1.0, 2.0, 3.0, 4.0 }; median(vd); // instantiates median with T == double The deduced template parameter type pervades the whole function: return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid];  As v is a vector, v[mid] is of type T 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 11

Template instantiation When a template function is called the compiler instantiates a version of the function based on concrete types supplied  Concrete types are deduced from arguments  Return type cannot be deduced  Once deduced all occurrences of those types are ‘replaced’ by concrete ones Requires the compiler to see all of the code  Compiler needs access to all of the sources  Templates are often fully defined in header files 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 12

Generic Functions and Types What’s an ‘appropriate type’ when instantiating a template  Median: types stored in the passed vector need to support addition and division with normal arithmetic meaning But subtle problems may occur  This is ok: find(homework.begin(), homework.end(), 0);  This is not (why?): accumulate(homework.begin(), homework.end(), 0); 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 13

Generic Functions and Types std::find: template Iterator find(Iterator first, Iterator last, T const& val) { for (/**/; first != last; ++first) if (*first == val) break; return first; } std::accumulate: template T accumulate(Iterator first, Iterator last, T val) { for (/**/; first != last; ++first) val = val + *first; return val; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 14

Generic Functions and Types std::max is supposed to get arguments of the same type: string::size_type maxlen = 0; maxlen = max(maxlen, name.size()); Implementation: template T const& max(T const& left, T const& right) { return left < right ? right : left; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 15

Generic Functions and Types Why do we have that restriction (before C++11)? Unfortunately, this does not work: template ??? const& max(T1 const& left, T2 const& right) { return left < right ? right : left; } But this does (C++11): template auto max(T1 const& left, T2 const& right) -> decltype(left < right ? right : left) { return left < right ? right : left; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 16

Generic Functions and Types And this does as well (C++14): template auto max(T1 const& left, T2 const& right) { return left < right ? right : left; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 17

Data-structure Independence The median function we wrote can be called for any vector, where T is an arithmetic type  Wouldn’t it be nice being able to use other containers as well (list, vector, map)?  Moreover, we would like to act on a part of the container, not always the full data set std::find: find(c.begin(), c.end(), val);// why? c.find(val); // why not? find(c, val); // why not? 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 18

Data-structure Independence Two questions, several answers:  By using iterators the library makes it possible to write a single ‘find’ function that can find a value in any contiguous part of any container  Even if we have to mention ‘c’ twice,  If we had c.find(val),  Then every container type ‘c’ needs to implement a member ‘find’  Moreover, if we had find(c, val),  Then we wouldn’t be able to use the algorithms for parts of a container  What about usage of rbegin()/rend() (i.e. reverse iterators) 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 19

Algorithms and Iterators Different containers expose iterators with different capabilities  std::vector exposes iterator allowing to ‘jump‘ to arbitrary element, std::list does not  Algorithms which rely on certain capabilities can‘t be used with all iterators  All iterators expose similar functionality using similar names, i.e. operator++() for increment std::find uses only simple operations (all containers) std::sort uses more complex operations (vectors, and strings only) 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 20

Algorithms and Iterators Library defines five iterator categories  Each corresponds to a specific set of exposed container operations  Each library algorithm states what iterator category is compatible  Possible to understand what containers are usable with which algorithms  Each category corresponds to access strategy for elements, also limits usable algorithms  For instance: single pass algorithms, or random access algorithms 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 21

Sequential Read-Only Access std::find: template Iterator find(Iterator first, Iterator last, T const& val) { for (/**/; first != last; ++first) if (*first == val) break; return first; } Requires iterator operators: !=, ==, ++, * (for reading), -> for member access  Input iterators Not possible to store a copy of the iterator ‘to go back’ All iterators we’ve seen so far are (at least) input iterators 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 22

Sequential Write-Only Access std::copy template Out copy(In begin, In end, Out dest) { while (begin != end) *dest++ = *begin++; return dest; } Required iterator operators: !=, ==, ++, * (for writing)  Output Iterators, example: std::back_inserter Implicit requirements:  Do not execute ++it more than once between assignments to *it  Do not assign a value to *it more than once without incrementing it Not possible to store a copy of the iterator to overwrite output 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 23

Sequential Read-Write Access std::replace template void replace(For beg, For end, X const& x, X const& y) { while (beg != end){ if (*beg == x) *beg = y; ++beg; } Required iterator operators: !=, ==, ++, * (for reading and writing), -> for member access  Forward iterators Storing copy of iterator possible! Very handy! 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 24

Reversible Access std::reverse template void reverse(Bi begin, Bi end) { while (begin != end) { --end; if (begin != end) swap(*begin++, *end); } Required iterator operators: !=, ==, ++, --, * (for reading and writing), -> for member access  Bidirectional iterators The standard-library container classes all support bidirectional iterators.  Except C++11 std::forward_list<> (singly linked list) 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 25

Random Access std::binary_search: template bool binary_search(Ran begin, Ran end, X const& x) { while (begin < end) { // find the midpoint of the range Ran mid = begin + (end - begin) / 2; // see which part of the range contains x; // keep looking only in that part if (x < *mid) end = mid; else if (*mid < x) begin = mid + 1; else // if we got here, then *mid == x so we're done return true; } return false; } 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 26

Random Access Required iterator operators:  !=, ==, ++, --, * (for reading and writing), -> for member access  Let’s assume p, q are iterators, n is integer  p + n, p - n, and n + p  p - q  p[n] (equivalent to *(p + n))  p q, p = q We’ve used std::sort Containers: std::vector, std::string  std::list is not random access (it’s bidirectional), why? 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 27

Iterator Ranges Algorithms take pair of iterators  c.begin() – refers to first element  c.end() – refers to first element after last (‘one off’) Allows simple handling of empty ranges, both iterators point to the one off element Allows for comparing iterators for equality (!=/==), no need to define notion of iterators being larger/smaller than others Allows to indicate ‘out of range’, see url_beg(), where we returned end (off by one) iterator if nothing was found Only caveat for end iterators is that they can’t be dereferenced 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 28

Input/Output Iterators Why are they separate from forward iterators?  (no container requires them) One reason is  Not all iterators come from containers  back_inserter, usable with any container supporting push_back  Iterators bound to streams: using iterator operations those allow to access istreams and ostreams 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 29

Input/Output Iterators The input stream iterator is an input-iterator type named istream_iterator: // read ints from the standard input and append them to v vector v; copy(istream_iterator (cin), istream_iterator (), back_inserter(v)); istream_iterators are templates!  Need to specify type to read from input  Same as for normal input operations, which are always typed as well  Default constructed istream_iterator denotes end of input 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 30

Input/Output Iterators The output stream iterator is an output-iterator type named ostream_iterator: // write the elements of v each separated from the other // by a space copy(v.begin(), v.end(), ostream_iterator (cout, " ")); ostream_iterator is a template as well  Need to specify type of required output  Second argument is separator (defaults to no separation) 3/26/2013 Lecture 18 CSC 1254, Spring 2015, Writing Generic Functions 31