c++ training datascope lawrence d’antonio

Post on 22-Feb-2016

25 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

C++ Training Datascope Lawrence D’Antonio. Lecture 10 An Overview of C++: The Standard Template Library. Why Should You Learn STL?. STL is generic. It involves data structures and algorithms that are designed to work on as wide a range of data types as possible. - PowerPoint PPT Presentation

TRANSCRIPT

C++ TrainingC++ TrainingDatascopeDatascope

Lawrence D’AntonioLawrence D’AntonioLecture 10Lecture 10

An Overview of C++:An Overview of C++:The Standard Template LibraryThe Standard Template Library

Why Should You Learn STL?Why Should You Learn STL? STL is generic. It involves data structures STL is generic. It involves data structures

and algorithms that are designed to work and algorithms that are designed to work on as wide a range of data types as on as wide a range of data types as possible.possible.

STL is useful. It provides a variety of basic STL is useful. It provides a variety of basic tools that are easy to learn and to use. tools that are easy to learn and to use. STL has a well-designed architecture that STL has a well-designed architecture that provides a variety of algorithms that can provides a variety of algorithms that can manipulate a number of data structures.manipulate a number of data structures.

Why Should You Learn STL?Why Should You Learn STL? STL is efficient. STL algorithms come with STL is efficient. STL algorithms come with

performance guarantees. For example, insertion performance guarantees. For example, insertion into a map data structure is guaranteed to be at into a map data structure is guaranteed to be at most logarithmic.most logarithmic.

STL is extensible.The components of STL may STL is extensible.The components of STL may be put together to create powerful generic be put together to create powerful generic libraries. For example, there exists an MTL libraries. For example, there exists an MTL (Matrix Template Library), a GTL (Graph (Matrix Template Library), a GTL (Graph Template Library), and Regex++, a regular Template Library), and Regex++, a regular expression library based on STL.expression library based on STL.

What is STL?What is STL?

The Standard Template Library (STL) is a The Standard Template Library (STL) is a powerful collection of generic data powerful collection of generic data structures and algorithms that is part of the structures and algorithms that is part of the standard library in C++. The algorithms in standard library in C++. The algorithms in STL are orthogonal to the data structures, STL are orthogonal to the data structures, in the sense that algorithms are designed in the sense that algorithms are designed to work without having to know details of to work without having to know details of the data structures to which they are being the data structures to which they are being applied.applied.

What is STL? 2What is STL? 2

In order for this process to work, data In order for this process to work, data containers are required to define the containers are required to define the concept of an iterator (i.e., objects that concept of an iterator (i.e., objects that define an addressing mechanism for the define an addressing mechanism for the data structure). These iterators are used in data structure). These iterators are used in turn by the STL algorithms to access the turn by the STL algorithms to access the data structure. data structure.

What is STL? 3What is STL? 3 Different algorithms require different types Different algorithms require different types

of access. of access. For example, the generic sorting For example, the generic sorting

algorithms in the STL require random algorithms in the STL require random access. This restricts the data structures access. This restricts the data structures that sorting algorithms can be used with to that sorting algorithms can be used with to ones that provide random access (in the ones that provide random access (in the standard library this includes arrays, standard library this includes arrays, strings, vectors, and deques).strings, vectors, and deques).

What is STL? 4What is STL? 4

Alexander Stepanov, the primary Alexander Stepanov, the primary developer of the STL, identifies four developer of the STL, identifies four principles that underlie the design of STL.principles that underlie the design of STL.

Generic programmingGeneric programming Abstractness without loss of efficiencyAbstractness without loss of efficiency Von Neumann computational modelVon Neumann computational model Value semanticsValue semantics

Generic programmingGeneric programming

Generic programming can be thought of Generic programming can be thought of as writing software components that can as writing software components that can be used for as wide a range of types as be used for as wide a range of types as possible. possible.

Stepanov states that generic programming Stepanov states that generic programming attempts to find the most abstract form of attempts to find the most abstract form of an efficient algorithm.an efficient algorithm.

Generic programming 2Generic programming 2 The central abstraction in STL is that of the The central abstraction in STL is that of the

concept. A concept is a set of requirements for concept. A concept is a set of requirements for data types. data types.

For example, a Sequence is a concept For example, a Sequence is a concept describing data containers that store elements in describing data containers that store elements in a linearly ordered range and allow for insertion a linearly ordered range and allow for insertion or deletion at any point in that range. or deletion at any point in that range.

Any data structure fitting these requirements is a Any data structure fitting these requirements is a model for the Sequence concept. STL defines model for the Sequence concept. STL defines three sequence types; vectors, lists, and three sequence types; vectors, lists, and deques.deques.

Generic programming 3Generic programming 3

Concepts can be classified and organized Concepts can be classified and organized in hierarchies. For example, one of the in hierarchies. For example, one of the primary concepts of the STL is that of the primary concepts of the STL is that of the Iterator. Iteration allows for movement Iterator. Iteration allows for movement from one address location in a data from one address location in a data structure to another. structure to another.

There are various categories of Iterators. There are various categories of Iterators.

Generic programming 4Generic programming 4 A ForwardIterator only allows movement in A ForwardIterator only allows movement in

one direction. There are two Iterator one direction. There are two Iterator concepts that the ForwardIterator refines, concepts that the ForwardIterator refines, the InputIterator and the OutputIterator. the InputIterator and the OutputIterator.

The InputIterator can only read from the The InputIterator can only read from the current location and allows movement current location and allows movement forward. The OutputIterator can only write forward. The OutputIterator can only write to the current location and allows to the current location and allows movement forward.movement forward.

Generic programming 5Generic programming 5 The algorithms that form the STL are The algorithms that form the STL are

themselves organized around concepts. themselves organized around concepts. A generic algorithm consists of an A generic algorithm consists of an

implementation and the set of implementation and the set of requirements that its arguments must requirements that its arguments must satisfy. satisfy.

For example, the STL algorithm For example, the STL algorithm reverse()reverse() will reverse the elements of any container will reverse the elements of any container that is a model of the Sequence concept.that is a model of the Sequence concept.

Generic programming 6Generic programming 6 Here is a non-generic gcd function.Here is a non-generic gcd function.int gcd(int x, int y)int gcd(int x, int y){{ while (y != 0) {while (y != 0) { int t = x % y;int t = x % y; x = y;x = y; y = t;y = t; }} return x < 0 ? -x : x; return x < 0 ? -x : x; }}

Generic programming 7Generic programming 7

This algorithm is fine as it goes, but a This algorithm is fine as it goes, but a generic version should be valid for other generic version should be valid for other algebraic quantities besides integers (in algebraic quantities besides integers (in fact, for any principal ideal domain). For fact, for any principal ideal domain). For example, we would want to extend the example, we would want to extend the algorithm to polynomials and Gaussian algorithm to polynomials and Gaussian integers. integers.

Generic programming 8Generic programming 8

One problem arises here, the return One problem arises here, the return statement, which is assuming that the gcd statement, which is assuming that the gcd returns a positive value, will only be valid returns a positive value, will only be valid for types that satisfy the requirement of for types that satisfy the requirement of being totally ordered. being totally ordered.

Generic programming 9Generic programming 9 Here is a generic gcd function.Here is a generic gcd function.template <class T>template <class T>T gcd(T x, T y)T gcd(T x, T y){{ while (y != 0) {while (y != 0) { T t = x % y;T t = x % y; x = y;x = y; y = t;y = t; }} return x;return x;}}

Generic programming 10Generic programming 10

In this case, the 'greatest' divisor that we In this case, the 'greatest' divisor that we are returning is only unique up to are returning is only unique up to multiplication by a unit. Each type will have multiplication by a unit. Each type will have its own concept of greatest (greatest its own concept of greatest (greatest degree for polynomials, greatest modulus degree for polynomials, greatest modulus for Gaussian integers). for Gaussian integers).

Generic programming 11Generic programming 11

To summarize (and perhaps oversimplify).To summarize (and perhaps oversimplify).   object-oriented programming = data object-oriented programming = data

abstraction + object types + type inheritanceabstraction + object types + type inheritance

generic programming = data abstraction + generic programming = data abstraction + generic types + concept refinementgeneric types + concept refinement

AbstractionAbstraction STL makes efficiency an important part of the STL makes efficiency an important part of the

design of the library. design of the library. Complexity guarantees are part of interface of Complexity guarantees are part of interface of

each STL component. each STL component. For example, there are three sequence For example, there are three sequence

containers, vector<Type>, list<Type>, containers, vector<Type>, list<Type>, deque<Type>. deque<Type>.

The C++ standard gives the following time The C++ standard gives the following time guarantees for element access, element guarantees for element access, element insert/delete, and range insert/delete.insert/delete, and range insert/delete.

Abstraction 2Abstraction 2

OperationOperation VectorVector DequeDeque ListListAccess at frontAccess at front ConstantConstant ConstantConstant ConstantConstant

Access at backAccess at back ConstantConstant ConstantConstant ConstantConstant

Random access Random access ConstantConstant ConstantConstant LinearLinear

Insert at frontInsert at front LinearLinear Constant*Constant* ConstantConstant

Insert at backInsert at back Constant*Constant* Constant*Constant* ConstantConstant

Random insertRandom insert LinearLinear LinearLinear ConstantConstant

Insert rangeInsert range LinearLinear LinearLinear ConstantConstant

Abstraction 3Abstraction 3 STL also provides associative containers that, in STL also provides associative containers that, in

general, store elements of the form (key, value), in general, store elements of the form (key, value), in some sort of tree structure (usually a red-black tree). some sort of tree structure (usually a red-black tree). There are four types of associative containers: There are four types of associative containers:

Sets (which are collections of unique keys without Sets (which are collections of unique keys without corresponding values).corresponding values).

Multisets (which allow for multiple occurrences of a Multisets (which allow for multiple occurrences of a key).key).

Maps (which store key, value pairs with keys being Maps (which store key, value pairs with keys being unique).unique).

Multisets (which store key, value pairs with multiple Multisets (which store key, value pairs with multiple keys possible). keys possible).

Abstraction 4Abstraction 4 The basic operations for associative The basic operations for associative

containers are, finding an element with a containers are, finding an element with a given key, inserting an element, erasing given key, inserting an element, erasing an element, erasing all elements pointed an element, erasing all elements pointed to by a key. to by a key.

In the following table, N represents the In the following table, N represents the number of elements in the container, K number of elements in the container, K represents the number of values represents the number of values corresponding to a particular key. corresponding to a particular key.

Abstraction 5Abstraction 5

OperationOperation SetSet MultisetMultiset MapMap MultimapMultimap

FindFind Log(N)Log(N) Log(N)Log(N) Log(N)Log(N) Log(N)Log(N)

InsertInsert Log(N)Log(N) Log(N)Log(N) Log(N)Log(N) Log(N)Log(N)

EraseErase Constant*Constant* Constant*Constant* Constant*Constant* Constant*Constant*

Erase KeyErase Key Log(N)Log(N) Log(N)+KLog(N)+K Log(N)Log(N) Log(N)+KLog(N)+K

Von Neumann ModelVon Neumann Model

Stepanov notes the significance of Stepanov notes the significance of addressing in the design of STL. addressing in the design of STL.

The STL containers provide services for The STL containers provide services for adding or deleting addresses to a data adding or deleting addresses to a data structure. Iterators can be seen as moving structure. Iterators can be seen as moving from one address to another in a from one address to another in a container.container.

Value SemanticsValue Semantics

In the STL containers own their elements. In the STL containers own their elements. When a container is copied, all elements When a container is copied, all elements are copied. When a container is are copied. When a container is destroyed, all objects it contains are in turn destroyed, all objects it contains are in turn destroyed. destroyed.

All copies in STL are deep copies.All copies in STL are deep copies. These value semantics imply that STL These value semantics imply that STL

containers can never overlap.containers can never overlap.

Value Semantics 2Value Semantics 2

Of course, for the sake of efficiency, one Of course, for the sake of efficiency, one can store pointers to larger structures in a can store pointers to larger structures in a container. container.

But this itself presents problems. One has But this itself presents problems. One has to adapt the comparison functions that to adapt the comparison functions that several STL containers and algorithms several STL containers and algorithms require to work with pointers. require to work with pointers.

Value Semantics 3Value Semantics 3 A more important consideration is the use A more important consideration is the use

of STL with polymorphic objects. of STL with polymorphic objects. Because of the use of value semantics in Because of the use of value semantics in

STL, polymorphic objects are either sliced STL, polymorphic objects are either sliced (i.e., only their base parts are copied or (i.e., only their base parts are copied or assigned) or, if pointers are used, there is assigned) or, if pointers are used, there is a problem of ownership of the object (e.g., a problem of ownership of the object (e.g., what should happen if the object is what should happen if the object is removed from the container). removed from the container).

Value Semantics 4Value Semantics 4 One solution to this problem is the use a One solution to this problem is the use a

type of smart pointer. type of smart pointer. For example, one can define a pointer For example, one can define a pointer

object containing a reference to a object containing a reference to a polymorphic object. polymorphic object.

When copying or assigning the smart When copying or assigning the smart pointer, a new copy of the referenced pointer, a new copy of the referenced object is made (with the correct dynamic object is made (with the correct dynamic type).type).

A Short History of STLA Short History of STL The first explorations of the concept of generic The first explorations of the concept of generic

programming go back to work of Alexander programming go back to work of Alexander Stepanov in the late '70s. Stepanov in the late '70s.

Later work at General Electric Research and Later work at General Electric Research and Development in collaboration with David Musser Development in collaboration with David Musser led to the development of a list processing led to the development of a list processing library in Ada, the first language to support library in Ada, the first language to support generic programming. generic programming.

This work, in 1987, was followed by additional This work, in 1987, was followed by additional work in Scheme work in Scheme

A Short History of STL 2A Short History of STL 2 Stepanov, in work at Bell Laboratories and then Stepanov, in work at Bell Laboratories and then

later at Hewlett-Packard Research Laboratories, later at Hewlett-Packard Research Laboratories, turned his attention to formulating generic turned his attention to formulating generic algorithms in C++. algorithms in C++.

He was particularly attracted to the C++ feature He was particularly attracted to the C++ feature of templates, which allow for parametrized types. of templates, which allow for parametrized types.

Bjarne Stroustrup, the developer of C++, Bjarne Stroustrup, the developer of C++, introduced templates in 1991, in the cfront introduced templates in 1991, in the cfront Release 3.0 Release 3.0

A Short History of STL 3A Short History of STL 3 While Stepanov was at Hewlett-Packard, Meng While Stepanov was at Hewlett-Packard, Meng

Lee joined his project and became a major Lee joined his project and became a major contributor to the library that was eventually contributor to the library that was eventually called STL. called STL.

Andrew Koenig of Bell Laboratories, a member Andrew Koenig of Bell Laboratories, a member of the X3J16 ANSI/ISO committee for C++ of the X3J16 ANSI/ISO committee for C++ standardization, invited Stepanov to present the standardization, invited Stepanov to present the basic ideas of the library at the November 1993 basic ideas of the library at the November 1993 X3J16 meeting. X3J16 meeting.

This led to request from the committee for This led to request from the committee for Stepanov and Lee to write a draft proposal for Stepanov and Lee to write a draft proposal for STL at the March 1994 committee meeting.STL at the March 1994 committee meeting.

A Short History of STL 4A Short History of STL 4 Further revisions and extensions were proposed Further revisions and extensions were proposed

to the STL at this point. to the STL at this point. The major extension, associative containers, The major extension, associative containers,

was implemented by David Musser. was implemented by David Musser. After this work, the STL proposal was accepted After this work, the STL proposal was accepted

by the ANSI committee at their July 1994 by the ANSI committee at their July 1994 meeting. meeting.

The document produced by Stepanov and Lee The document produced by Stepanov and Lee was accepted into the X3J16 draft standard.was accepted into the X3J16 draft standard.

A Short History of STL 5A Short History of STL 5

The dissemination of the STL became The dissemination of the STL became widespread with the decision by HP, in widespread with the decision by HP, in August 1994, to make the library freely August 1994, to make the library freely available on the Internet. available on the Internet.

This implementation, due primarily to This implementation, due primarily to Stepanov, Lee, and Musser, is the basis Stepanov, Lee, and Musser, is the basis for all future versions of the STL.for all future versions of the STL.

A Short History of STL 6A Short History of STL 6 In 1996 Stepanov joined SGI and together with In 1996 Stepanov joined SGI and together with

Matthew Austern and Hans Boehm, worked on Matthew Austern and Hans Boehm, worked on an implementation of the STL. an implementation of the STL.

This implementation includes various extensions This implementation includes various extensions of the STL, such as thread-safe memory of the STL, such as thread-safe memory allocation and hash tables. allocation and hash tables.

It should be noted that the extensions in the SGI It should be noted that the extensions in the SGI version of the library have not yet been accepted version of the library have not yet been accepted into the C++ standard. into the C++ standard.

This implementation may be downloaded, This implementation may be downloaded, together with extensive documentation on the together with extensive documentation on the library, at library, at http://http://www.sgi.com/tech/stlwww.sgi.com/tech/stl//

STL by exampleSTL by example

First, to see the power of STL and how it First, to see the power of STL and how it functions let us look at a simple series of functions let us look at a simple series of examples, adapted from David Harvey's examples, adapted from David Harvey's online STL tutorial: online STL tutorial: http://www.davethehat.com/articles/eff_stl.http://www.davethehat.com/articles/eff_stl.htmhtm

STL by example 2STL by example 2

Word Copy Example Word Copy Example

The task is to write a function that reads in The task is to write a function that reads in strings from an input stream, sorts them, strings from an input stream, sorts them, eliminates duplicates, and then prints the eliminates duplicates, and then prints the results to an output stream, one word per results to an output stream, one word per line. line.

STL by example 3STL by example 3

Version 1 (Non-STL)Version 1 (Non-STL)

This version is given in pseudo-code to This version is given in pseudo-code to spare the reader the gory details (which spare the reader the gory details (which they can presumably fill in for they can presumably fill in for themselves).themselves).

STL by example 4STL by example 4ostream& wordcopy(istream &in, ostream &out)ostream& wordcopy(istream &in, ostream &out){{ string s; //string to be readstring s; //string to be read //Also need a container to store the strings//Also need a container to store the strings   while( !in.eof() && in >> s ) {while( !in.eof() && in >> s ) { //store s in container//store s in container }}   //Sort the container in alphabetical order //Sort the container in alphabetical order  //Remove duplicates, this gets ugly if you used an array //Remove duplicates, this gets ugly if you used an array  //Print each string to output stream, one per line//Print each string to output stream, one per line   return out;return out;}}

STL by example 5STL by example 5 Version 2 (STL using vector container)Version 2 (STL using vector container)ostream& wordcopy(istream &in, ostream&out)ostream& wordcopy(istream &in, ostream&out){{ string s; //string to be readstring s; //string to be read vector<string> v; vector<string> v; //STL vector container for the strings//STL vector container for the strings

   while( !in.eof() && in >> s )while( !in.eof() && in >> s ) v.push_back(s); v.push_back(s); //inserts s at end of container//inserts s at end of container

STL by example 6STL by example 6//STL sort algorithm//STL sort algorithmsort(v.begin(), v.end()); sort(v.begin(), v.end());

   //Use the STL unique() to 'eliminate‘ duplicates//Use the STL unique() to 'eliminate‘ duplicates //unique 'removes' consecutive duplicates//unique 'removes' consecutive duplicates vector<string>::iterator p = vector<string>::iterator p =

unique(v.begin(), v.end());unique(v.begin(), v.end());   //Now send results to output//Now send results to output for(vector<string>::iterator i = v.begin(); i != p; i++)for(vector<string>::iterator i = v.begin(); i != p; i++) out << *i << '\n';out << *i << '\n'; return out;return out;}}

STL by example 7STL by example 7 A couple of comments on this version.A couple of comments on this version.

The use of iterator is an essential part of The use of iterator is an essential part of STL. Iterators are used to traverse STL. Iterators are used to traverse containers, and to add or remove items containers, and to add or remove items from containers. from containers.

Each container-type has a corresponding Each container-type has a corresponding iterator-type. Vectors use random-access iterator-type. Vectors use random-access iterators. iterators.

STL by example 8STL by example 8 The unique algorithm has a quirk that one must The unique algorithm has a quirk that one must

get used to. get used to. Since it is a generic algorithm, and hence knows Since it is a generic algorithm, and hence knows

nothing about the underlying organization of the nothing about the underlying organization of the data it is being applied to, it cannot actually data it is being applied to, it cannot actually remove duplicates from the container. remove duplicates from the container.

What it in fact does is to place any duplicates at What it in fact does is to place any duplicates at the end of the container. After the algorithm is the end of the container. After the algorithm is completed, there will be a range of non-completed, there will be a range of non-duplicates, say in positions [first,last). The duplicates, say in positions [first,last). The function will return position last. function will return position last.

unique()unique() algorithm algorithmtemplate<class FwdIt>template<class FwdIt>FwdIt unique(FwdIt F, FwdIt L)FwdIt unique(FwdIt F, FwdIt L){{ FwdIt X = F; //X will step through duplicatesFwdIt X = F; //X will step through duplicates FwdIt Fb = F; //Fb will store position of first duplicateFwdIt Fb = F; //Fb will store position of first duplicate

for( *X++ = *Fb; ++F != L; ) {for( *X++ = *Fb; ++F != L; ) { if( !(*Fb == *F) ) {if( !(*Fb == *F) ) { Fb = F;Fb = F; *X++ = *Fb;*X++ = *Fb; }} }} return X;return X;}}

unique()unique() algorithm 2 algorithm 2main() {main() { int A[ ] = {1,1,1,2,3,3};int A[ ] = {1,1,1,2,3,3}; int *p = std::unique(&A[0],&A[6]);int *p = std::unique(&A[0],&A[6]); for(int *q = &A[0]; q != p; q++)for(int *q = &A[0]; q != p; q++) std::cout << *q << ' ';std::cout << *q << ' '; std::cout << '\n';std::cout << '\n'; return 0;return 0;}}

unique()unique() algorithm 3 algorithm 3template<class FwdIt, class BinPred>template<class FwdIt, class BinPred>FwdIt unique(FwdIt F, FwdIt L, BinPred P)FwdIt unique(FwdIt F, FwdIt L, BinPred P){{ FwdIt X = F;FwdIt X = F; FwdIt Fb = F;FwdIt Fb = F;

for( *X++ = *Fb; ++F != L; ) {for( *X++ = *Fb; ++F != L; ) { if( !P(*Fb,*F) ) {if( !P(*Fb,*F) ) { Fb = F;Fb = F; *X++ = *Fb;*X++ = *Fb; }} }} return X;return X;}}

unique()unique() algorithm 4 algorithm 4

Consider the following predicateConsider the following predicateclass P {class P {public:public:

bool operator()(int x, int y) {bool operator()(int x, int y) {return ((x % 2) != (y%2));return ((x % 2) != (y%2));

}}};};

unique()unique() algorithm 5 algorithm 5main() {main() { int A[ ] = {1,1,1,2,3,3};int A[ ] = {1,1,1,2,3,3};

int *p = unique(&A[0],&A[6],P());int *p = unique(&A[0],&A[6],P()); for(int *q = &A[0]; q != p; q++)for(int *q = &A[0]; q != p; q++) std::cout << *q << ' ';std::cout << *q << ' '; std::cout << '\n';std::cout << '\n'; return 0;return 0;}}

STL by example 9STL by example 9 Version 3 (STL using set container)Version 3 (STL using set container) A student studying STL quickly learns A student studying STL quickly learns

about the benefits of the STL about the benefits of the STL associative containers. associative containers.

For the task at hand, the set container For the task at hand, the set container is particularly useful. Data in a set is is particularly useful. Data in a set is kept in sorted order, and no duplicates kept in sorted order, and no duplicates are allowed. This is exactly what we are allowed. This is exactly what we want.want.

STL by example 10STL by example 10

ostream& wordcopy(istream &in, ostream &out)ostream& wordcopy(istream &in, ostream &out){{

string s; //string to be readstring s; //string to be readset<string> words; //STL set container for the stringsset<string> words; //STL set container for the strings

while( !in.eof() && in >> s )while( !in.eof() && in >> s ) words.insert(s); //Insert in sorted orderwords.insert(s); //Insert in sorted order

STL by example 11STL by example 11

//Now send results to output//Now send results to outputfor(set<string>::iterator i = words.begin(); for(set<string>::iterator i = words.begin();

i != words.end(); i++)i != words.end(); i++) out << *i << '\n';out << *i << '\n';  

return out;return out;}}

STL by example 12STL by example 12 Note, if the input string s is already in set, Note, if the input string s is already in set,

then the insertion does nothing. then the insertion does nothing. The insert function returns a pair The insert function returns a pair

consisting of an iterator and a bool. consisting of an iterator and a bool. If the insertion was successful, it returns If the insertion was successful, it returns

(new position, true). (new position, true). If the insertion failed, because the value If the insertion failed, because the value

was already in the set, the return will be was already in the set, the return will be (existing position, false).(existing position, false).

STL by example 13STL by example 13 Version 4 (STL using sets and stream Version 4 (STL using sets and stream

adaptors)adaptors) Copying operations in the STL often make Copying operations in the STL often make

use of adaptors. An adaptor makes one use of adaptors. An adaptor makes one object act like another. object act like another.

A stream adaptor makes an input or output A stream adaptor makes an input or output stream look like a container to an STL stream look like a container to an STL algorithm. algorithm.

In general, the copy algorithms in the library In general, the copy algorithms in the library use source and destination containers. But use source and destination containers. But by using adaptors, we can copy from or to a by using adaptors, we can copy from or to a stream.stream.

STL by example 14STL by example 14 One difficulty in using the copy algorithms One difficulty in using the copy algorithms

is the fact that the destination container is is the fact that the destination container is assumed to have the space to hold the assumed to have the space to hold the data copied over from the source. data copied over from the source.

If this is not the case, as in the example If this is not the case, as in the example below, then an inserter object must be below, then an inserter object must be used for the destination (the inserter will used for the destination (the inserter will call the underlying insert() member call the underlying insert() member function).function).

STL by example 15STL by example 15ostream& wordcopy(istream &in, ostream &out)ostream& wordcopy(istream &in, ostream &out){{

set<string> words; set<string> words; //STL set container for the strings//STL set container for the strings

  //Read in from istream and store in set//Read in from istream and store in setcopy(istream_iterator<string>(in),copy(istream_iterator<string>(in), istream_iterator<string>(), istream_iterator<string>(), inserter(words, words.begin()));inserter(words, words.begin()));

STL by example 16STL by example 16

//Now send results to output//Now send results to outputcopy(words.begin(), words.end(), copy(words.begin(), words.end(),

ostream_iterator<string>(out, "\ostream_iterator<string>(out, "\n"));n"));

  return out;return out;

}}

STL by example 17STL by example 17 A few comments are in order. A few comments are in order. The adaptor, istream_iterator, needs to know the The adaptor, istream_iterator, needs to know the

data type that is being read, string in this case.data type that is being read, string in this case. Note that the extraction operator >> is used by Note that the extraction operator >> is used by

istream_iterator, so it can only read types for istream_iterator, so it can only read types for which this operator has been defined. which this operator has been defined.

Also, we have used a constructor to create the Also, we have used a constructor to create the istream_iterator and to give it the input stream to istream_iterator and to give it the input stream to read from. read from.

STL by example 18STL by example 18 The default constructor for istream_iterator is The default constructor for istream_iterator is

used to create an end of file position that is used used to create an end of file position that is used to terminate the algorithm.to terminate the algorithm.

The mechanism to make this work is a little The mechanism to make this work is a little tricky, since the default istream_iterator doesn't tricky, since the default istream_iterator doesn't know what file it is supposed to be the end of!know what file it is supposed to be the end of!

Here is the way it works. Istream iterators keep a Here is the way it works. Istream iterators keep a data member that is a pointer, lets call it Istr, to data member that is a pointer, lets call it Istr, to the istream it traverses. the istream it traverses.

STL by example 19STL by example 19 Suppose we declare (note the string type Suppose we declare (note the string type

plays no role) two istream iterators and plays no role) two istream iterators and then increment one of them. then increment one of them.

istream_iterator<string> i(in_file);istream_iterator<string> i(in_file);//i.Istr = &in_file//i.Istr = &in_file

istream_iterator<string> j; istream_iterator<string> j; //j.Istr = 0//j.Istr = 0

++i;++i;

STL by example 20STL by example 20

The increment operator for i calls an The increment operator for i calls an internal read function that uses the internal read function that uses the extraction operator >>. extraction operator >>.

If the extraction fails, i.Istr is set equal to 0, If the extraction fails, i.Istr is set equal to 0, and then iterators i, j will compare as being and then iterators i, j will compare as being equal.equal.

STL by example 21STL by example 21

A third comment on the above version is A third comment on the above version is that the ostream_iterator constructor takes that the ostream_iterator constructor takes two arguments, the ostream and a string two arguments, the ostream and a string to be used as a delimiter between outputs. to be used as a delimiter between outputs.

Iterator adaptorsIterator adaptors

Let’s look in more detail at the iterator Let’s look in more detail at the iterator adaptors adaptors istream_iteratoristream_iterator, , ostream_iteratorostream_iterator, , insert_iteratorinsert_iterator (which (which inserterinserter returns).returns).

istream_iteratoristream_iteratortemplate<class T, class E = char, template<class T, class E = char,

class Tr = std::char_traits<E> >class Tr = std::char_traits<E> >class istream_iterator {class istream_iterator {public:public: typedef istream_iterator<T,E,Tr> Iter;typedef istream_iterator<T,E,Tr> Iter; typedef E char_type; typedef E char_type; typedef Tr traits_type;typedef Tr traits_type; typedef std::basic_istream<E,Tr> istream_type;typedef std::basic_istream<E,Tr> istream_type;

istream_iterator 2istream_iterator 2

protected:protected: T val;T val; istream_type *Istr;istream_type *Istr; void Getval() {void Getval() { if (Istr != 0 && !(*Istr >> val))if (Istr != 0 && !(*Istr >> val)) Istr = 0;Istr = 0; }}

istream_iterator 3istream_iterator 3public:public: istream_iterator()istream_iterator() : Istr(0) {}: Istr(0) {} istream_iterator(istream_type &I)istream_iterator(istream_type &I) : Istr(&I) { Getval(); }: Istr(&I) { Getval(); } const T& operator*() constconst T& operator*() const { return val; } { return val; } const T* operator->() constconst T* operator->() const { return &**this; }{ return &**this; } Iter &operator++()Iter &operator++() { Getval(); return *this; }{ Getval(); return *this; } Iter operator++(int)Iter operator++(int) { Iter temp; Getval(); return temp; }{ Iter temp; Getval(); return temp; }

istream_iterator 4istream_iterator 4bool Equal(const Iter& x) const bool Equal(const Iter& x) const { return Istr == x.Istr; }{ return Istr == x.Istr; }};}; template<class T, class E, class Tr>template<class T, class E, class Tr>bool operator==(const istream_iterator<T,E,Tr> &x,bool operator==(const istream_iterator<T,E,Tr> &x, const istream_iterator<T,E,Tr> &y)const istream_iterator<T,E,Tr> &y) { return x.Equal(y); }{ return x.Equal(y); } template<class T, class E, class Tr> template<class T, class E, class Tr> bool operator!=(const istream_iterator<T,E,Tr> &x,bool operator!=(const istream_iterator<T,E,Tr> &x, const istream_iterator<T,E,Tr> &y)const istream_iterator<T,E,Tr> &y) { return !(x == y); }{ return !(x == y); }

ostream_iteratorostream_iteratortemplate<class T, class E = char, template<class T, class E = char,

class Tr = std::char_traits<E> >class Tr = std::char_traits<E> >class ostream_iterator {class ostream_iterator {public:public: typedef ostream_iterator<T,E,Tr> Iter;typedef ostream_iterator<T,E,Tr> Iter; typedef T value_type;typedef T value_type; typedef E char_type;typedef E char_type; typedef Tr traits_type;typedef Tr traits_type; typedef std::basic_ostream<E,Tr> ostream_type;typedef std::basic_ostream<E,Tr> ostream_type;protected:protected: const E *Delim; const E *Delim; ostream_type *Ostr;ostream_type *Ostr;

ostream_iterator 2ostream_iterator 2public:public: ostream_iterator(ostream_type &O, const E *D = 0)ostream_iterator(ostream_type &O, const E *D = 0) : Ostr(&O), Delim(D) { }: Ostr(&O), Delim(D) { }

Iter &operator=(const T&x)Iter &operator=(const T&x) { *Ostr << x;{ *Ostr << x; if (Delim != 0)if (Delim != 0) *Ostr << Delim;*Ostr << Delim; }}

ostream_iterator 3ostream_iterator 3

const T& operator*() constconst T& operator*() const { return *this; }{ return *this; } Iter &operator++()Iter &operator++() { return *this; }{ return *this; } Iter operator++(int)Iter operator++(int) { return *this; }{ return *this; }};};

insert_iteratorinsert_iteratortemplate<class C>template<class C>class insert_iterator {class insert_iterator {public:public: typedef C container_type;typedef C container_type; typedef typename C::reference reference_type;typedef typename C::reference reference_type; typedef typename C::value_type value_type;typedef typename C::value_type value_type;

protected:protected: C *container;C *container; typename C::iterator iter;typename C::iterator iter;

insert_iterator 2insert_iterator 2public:public: insert_iterator(C &X, typename C::iterator I)insert_iterator(C &X, typename C::iterator I) :container(&X), iter(I) {}:container(&X), iter(I) {}

insert_iterator<C>& operator=(insert_iterator<C>& operator=( typename C::const_reference val)typename C::const_reference val) { iter = container->insert(iter,val);{ iter = container->insert(iter,val); ++iter;++iter; return *this; return *this; }}

insert_iterator 3insert_iterator 3 insert_iterator<C>& operator*()insert_iterator<C>& operator*()

{ return *this; }{ return *this; } insert_iterator<C>& operator++() insert_iterator<C>& operator++() { return *this; }{ return *this; } insert_iterator<C>& operator++(int)insert_iterator<C>& operator++(int) { return *this; }{ return *this; }};}; template<class C,class Iter>template<class C,class Iter>insert_iterator<C> inserter(C& X, Iter I)insert_iterator<C> inserter(C& X, Iter I){{ return insert_iterator<C>(X, C::iterator(I));return insert_iterator<C>(X, C::iterator(I));}}

STL by example 22STL by example 22 Version 5 (STL using transform() for string Version 5 (STL using transform() for string

conversion)conversion) The problem of sorting strings is The problem of sorting strings is

complicated by the issue of case. The complicated by the issue of case. The versions above are case-sensitive (so "The" versions above are case-sensitive (so "The" and "the" would both be in the output). and "the" would both be in the output).

A simple way to handle is to convert the A simple way to handle is to convert the strings to lower case as they are being read. strings to lower case as they are being read. But we would like to do this while keeping But we would like to do this while keeping the simplicity of version 4.the simplicity of version 4.

STL by example 23STL by example 23

This is where the transform algorithm This is where the transform algorithm comes into play. This function will comes into play. This function will apply a function (or function object), to apply a function (or function object), to each element in a source container, each element in a source container, and pass the return value of this and pass the return value of this function to the destination container.function to the destination container.

STL by example 24STL by example 24ostream& wordcopy(istream &in, ostream &out)ostream& wordcopy(istream &in, ostream &out){{

set<string> words; set<string> words; //STL set container for the strings//STL set container for the strings

  //Read in from istream, convert to lower case,//Read in from istream, convert to lower case,//Store in set//Store in settransform(istream_iterator<string>(in),transform(istream_iterator<string>(in),

istream_iterator(),istream_iterator(), inserter(words, words.begin()), inserter(words, words.begin()),

to_lower); to_lower);

STL by example 25STL by example 25

//Now send results to output//Now send results to outputcopy(words.begin(), words.end(),copy(words.begin(), words.end(),

ostream_iterator<string>(out, "\ostream_iterator<string>(out, "\n"));n"));

  return out;return out;

}}

STL by example 26STL by example 26 Here is the function to_lowerHere is the function to_lowerstring to_lower(const string &s)string to_lower(const string &s){{ string temp(s.size(),0);string temp(s.size(),0); for(int i = 0; i < s.size(); i++) for(int i = 0; i < s.size(); i++) temp[i] = tolower(s[i]);temp[i] = tolower(s[i]); return temp;return temp;} }

STL by example 27STL by example 27

Version 6 (STL with a different sorting Version 6 (STL with a different sorting criterion)criterion)

In this version we want the strings sorted In this version we want the strings sorted according to the following criterion. according to the following criterion.

The strings should be printed out The strings should be printed out according to order of their word length. If according to order of their word length. If two strings are the same length, then print two strings are the same length, then print out in alphabetical order.out in alphabetical order.

STL by example 28STL by example 28

To accomplish this we must give the set To accomplish this we must give the set container a comparison function object. container a comparison function object.

A function object (called a functor) is an A function object (called a functor) is an object with an overloaded function call object with an overloaded function call operator.operator.

STL by example 29STL by example 29struct lengthcomp {struct lengthcomp { bool operator() (const string &s1, const string &s2)bool operator() (const string &s1, const string &s2)

constconst

{{ return return

( s1.size() < s2.size() ) || ( s1.size() < s2.size() ) || ( (s1.size() == s2.size()) && (s1 < s2) );( (s1.size() == s2.size()) && (s1 < s2) );

}}};};

STL by example 30STL by example 30

The only other change we make is:The only other change we make is:

set<string,lengthcomp> words; set<string,lengthcomp> words;

How Much C++ Do You Need to How Much C++ Do You Need to Know for STL?Know for STL?

Template MetaprogrammingTemplate Metaprogramming Templates can be viewed as an interpreted Templates can be viewed as an interpreted

programming language. For example, consider programming language. For example, consider the following example:the following example:

template<int N>template<int N>struct Factorial {struct Factorial { enum { value = N * Factorial<N-1>::value };enum { value = N * Factorial<N-1>::value };};};

How Much …? 2How Much …? 2

//Specialized version//Specialized versiontemplate <>template <>struct Factorial<1> {struct Factorial<1> { enum { value = 1 };enum { value = 1 };};};  //...//...cout << '5!= ' << Factorial<5>::value;cout << '5!= ' << Factorial<5>::value;

How Much …? 3How Much …? 3 Traits classesTraits classes Traits are a method for associating information Traits are a method for associating information

about related types, values and functions with a about related types, values and functions with a template parameter type. template parameter type.

Traits are used in several parts of the STL, but Traits are used in several parts of the STL, but especially with iterators. especially with iterators.

Consider an example from the Nathan Myers Consider an example from the Nathan Myers paper that introduced the concept of traits to the paper that introduced the concept of traits to the C++ community.C++ community.

How Much …? 4How Much …? 4 Myers invented traits to handle a certain Myers invented traits to handle a certain

problem with the C++ I/O library. problem with the C++ I/O library. The C I/O library is meant to work with the char The C I/O library is meant to work with the char

type. But C++ is meant to be a reusable, type. But C++ is meant to be a reusable, extensible language. extensible language.

So that the design of the iostream library should, So that the design of the iostream library should, as far as possible, support the extension of the as far as possible, support the extension of the I/O routines to generic character types (different I/O routines to generic character types (different character sets, different size character types, character sets, different size character types, etc.). etc.).

How Much …? 5How Much …? 5 Consider the streambuf class, which is the Consider the streambuf class, which is the

central class in the iostream library. In the central class in the iostream library. In the original version of C++, streambuf was defined original version of C++, streambuf was defined in the form:in the form:

class streambuf {class streambuf { int sgetc(); //return the next character or EOFint sgetc(); //return the next character or EOF int sgetn(char*, int N); //get N charactersint sgetn(char*, int N); //get N characters};};

How Much …? 6How Much …? 6

Suppose we want to parametrize this class Suppose we want to parametrize this class with respect to character type. with respect to character type.

We have a problem with the return type of We have a problem with the return type of sgetc(). If we are using a different sgetc(). If we are using a different character type, then we may need a character type, then we may need a different type to represent EOF. different type to represent EOF.

One solution is to also make the return One solution is to also make the return type of sgetc() a type parameter.type of sgetc() a type parameter.

How Much …? 7How Much …? 7

template<class charT, class intT>template<class charT, class intT>class basic_stream_buf {class basic_stream_buf { intT sgetc();intT sgetc(); int sgetn(charT*, int N);int sgetn(charT*, int N);};};

How Much …? 8How Much …? 8 This has two problems. This has two problems. First of all it is annoying for the user to First of all it is annoying for the user to

have to remember the type of the end-of-have to remember the type of the end-of-file marker. file marker.

Second, and perhaps more important, is Second, and perhaps more important, is the question of how sgetc() should be the question of how sgetc() should be written. written.

What should it actually return in the case What should it actually return in the case that the end of file is found?that the end of file is found?

How Much …? 9How Much …? 9

The traits technique works as follows. The traits technique works as follows. One defines a character traits class, which One defines a character traits class, which

gives the properties (i.e., the traits) for gives the properties (i.e., the traits) for each character type for which we want to each character type for which we want to use the iostream library. use the iostream library.

How Much …? 10How Much …? 10

One defines the default traits class,One defines the default traits class,template<class charT>template<class charT>struct ios_char_traits { };struct ios_char_traits { }; The default traits class is empty because The default traits class is empty because

what are the traits of an arbitrary character what are the traits of an arbitrary character type?type?

One can specialize this class for specific One can specialize this class for specific character types.character types.

How Much …? 11How Much …? 11

Here is the specialized version for char.Here is the specialized version for char.

struct ios_char_traits<char> { struct ios_char_traits<char> { typedef char char_type; typedef char char_type; typedef int int_type; typedef int int_type; static inline int_type eof() { return EOF; } static inline int_type eof() { return EOF; }

}; };

How Much …? 12How Much …? 12 Here is the specialized version for wide Here is the specialized version for wide

char.char.

struct ios_char_traits<wchar_t> { struct ios_char_traits<wchar_t> { typedef wchar_t char_type; typedef wchar_t char_type; typedef wint_t int_type; typedef wint_t int_type; static inline int_type eof() { return WEOF; }static inline int_type eof() { return WEOF; }

}; };

How Much …? 13How Much …? 13 Here is the revised streambuf class.Here is the revised streambuf class.template <class charT> class basic_streambuf { template <class charT> class basic_streambuf { public: public:

typedef ios_char_traits<charT> traits_type; typedef ios_char_traits<charT> traits_type; typedef traits_type::int_type int_type; typedef traits_type::int_type int_type; int_type eof() { return traits_type::eof(); }int_type eof() { return traits_type::eof(); }int_type sgetc();int_type sgetc();int_type sbumpc(); int_type sbumpc(); int_type snextc();int_type snextc();int sgetn(charT*, int N); int sgetn(charT*, int N);

}; };

A Short Tour of STLA Short Tour of STL The components of STLThe components of STL ConceptsConcepts IteratorsIterators Iterator AdaptorsIterator Adaptors ContainersContainers Container AdaptorsContainer Adaptors AlgorithmsAlgorithms FunctorsFunctors AllocatorsAllocators

Basic ConceptsBasic Concepts

AssignableAssignable Concept:Concept: A type is Assignable if it allows A type is Assignable if it allows

for copying objects of that type and for for copying objects of that type and for assigning values to variables of that type. assigning values to variables of that type.

Operations:Operations: copy constructor and copy constructor and operator=operator=

Models:Models: All built-in types and STL All built-in types and STL containers, except for const types. containers, except for const types.

Basic Concepts 2Basic Concepts 2

Default ConstructibleDefault Constructible Concept:Concept: A type is Default Constructible if A type is Default Constructible if

it has a default constructor. it has a default constructor. Operations:Operations: Default constructor Default constructor Models:Models: All built-in types and STL All built-in types and STL

containers. containers.

Basic Concepts 3Basic Concepts 3 Equality ComparableEquality Comparable Concept:Concept: A type is Equality Comparable if two A type is Equality Comparable if two

values of this type can be compared for equality values of this type can be compared for equality using the == operator, and this operator must using the == operator, and this operator must define an equivalence relation. define an equivalence relation.

Operations:Operations: == and != == and != Models:Models: All built-in numeric and pointer types. All built-in numeric and pointer types.

Any STL container of the form Container<T> will Any STL container of the form Container<T> will be Equality Comparable if and only if T is be Equality Comparable if and only if T is Equality Comparable. Equality Comparable.

Basic Concepts 4Basic Concepts 4 Less Than ComparableLess Than Comparable Concept:Concept: A type is LessThan Comparable if two A type is LessThan Comparable if two

values of this type can be compared using the < values of this type can be compared using the < operator, and this operator must define a partial operator, and this operator must define a partial ordering. The relation, x strictly divides y, is a ordering. The relation, x strictly divides y, is a partial order for integers that is not a total order.partial order for integers that is not a total order.

Operations:Operations: <, >, <=, >= <, >, <=, >= Models:Models: All built-in numeric types. Pointers All built-in numeric types. Pointers

storing addresses within the same array. storing addresses within the same array. Random Access Iterators traversing the same Random Access Iterators traversing the same container. container.

Basic Concepts 5Basic Concepts 5 Strict Weakly ComparableStrict Weakly Comparable Concept:Concept: A type is Strict Weakly Comparable if A type is Strict Weakly Comparable if

two values of this type can be compared using two values of this type can be compared using the < operator, and this operator defines an the < operator, and this operator defines an equivalence relation in the following sense. Two equivalence relation in the following sense. Two values, x and y, are considered equivalent if values, x and y, are considered equivalent if both x < y and y < x are false. Case-insensitive both x < y and y < x are false. Case-insensitive string comparison is a strict weak ordering that string comparison is a strict weak ordering that is not a total ordering. is not a total ordering.

Basic Concepts 6Basic Concepts 6

Refines:Refines: LessThan Comparable LessThan Comparable Models:Models: All built-in numeric types. Pointers All built-in numeric types. Pointers

storing addresses within the same array. storing addresses within the same array. Random Access Iterators traversing the Random Access Iterators traversing the same container.same container.

IteratorsIterators

An iterator is a generalization of the An iterator is a generalization of the concept of a pointer.concept of a pointer.

An iterator makes it possible to traverse a An iterator makes it possible to traverse a range of objects.range of objects.

Algorithms in STL generally manipulate Algorithms in STL generally manipulate iterators, instead of dealing with data iterators, instead of dealing with data structures directly.structures directly.

Iterator ConceptIterator Concept

Trivial iteratorTrivial iterator Input IteratorInput Iterator Output IteratorOutput Iterator Forward IteratorForward Iterator Bidirectional IteratorBidirectional Iterator Random Access IteratorRandom Access Iterator

Trivial IteratorTrivial Iterator

Concept:Concept: An object is a Trivial Iterator if it An object is a Trivial Iterator if it can be dereferenced. A Trivial Iterator may can be dereferenced. A Trivial Iterator may be mutable (its dereferenced value may be be mutable (its dereferenced value may be modified) or constant (the dereferenced modified) or constant (the dereferenced value cannot be modified). value cannot be modified).

Refines:Refines: Assignable, Equality Comparable Assignable, Equality Comparable

Trivial Iterator 2Trivial Iterator 2

Operations:Operations: Dereference: *p (p must be Dereference: *p (p must be

dereferenceable)dereferenceable) Dereference Assignment: *p = x (p must Dereference Assignment: *p = x (p must

be mutable)be mutable) Member Access: p->m (p must be Member Access: p->m (p must be

dereferenceable)dereferenceable) Equality: p == q (same as &*p == &*q)Equality: p == q (same as &*p == &*q)

Trivial Iterator 3Trivial Iterator 3

Models:Models: All pointer and iterator types All pointer and iterator types

Input IteratorInput Iterator Concept:Concept: An object is an input iterator if it An object is an input iterator if it

can be dereferenced and incremented. An can be dereferenced and incremented. An input iterator must give read access to its input iterator must give read access to its dereferenced value, but not necessarily dereferenced value, but not necessarily write access. Also, an input iterator does write access. Also, an input iterator does not necessarily support a multipass not necessarily support a multipass algorithm. algorithm.

Input iterators may be mutuable or Input iterators may be mutuable or constant.constant.

Input Iterator 2Input Iterator 2

Refines:Refines: Trivial Iterator Trivial Iterator Associated Types:Associated Types: iterator_traits<X>::value_typeiterator_traits<X>::value_type The type of the object dereferenced by The type of the object dereferenced by

iteratoriterator iterator_traits<X>::difference_typeiterator_traits<X>::difference_type A signed integral type representing the A signed integral type representing the

distance from one iterator to another.distance from one iterator to another.

Input Iterator 3Input Iterator 3 iterator_traits<X>::referenceiterator_traits<X>::reference Reference to the iterator’s value type.Reference to the iterator’s value type. iterator_traits<X>::pointeriterator_traits<X>::pointer Pointer to the iterator’s value type.Pointer to the iterator’s value type. iterator_traits<X>::iterator_categoryiterator_traits<X>::iterator_category One of the iterator tag types: input_iterator_tag, One of the iterator tag types: input_iterator_tag,

forward_iterator_tag, bidirectional_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tagrandom_access_iterator_tag

Input Iterator 4Input Iterator 4 Definitions:Definitions: An iterator is An iterator is past-the-endpast-the-end if it points if it points

beyond the last element of a container.beyond the last element of a container. An input iterator An input iterator jj is reachable from input is reachable from input

iterator iterator ii after applying ++ after applying ++ii a number of a number of times, we have i == j.times, we have i == j.

The notation The notation [i,j)[i,j) refers to a range of refers to a range of iterators beginning with I and up to but not iterators beginning with I and up to but not including j.including j.

Input Iterator 5Input Iterator 5

Operations:Operations: Those of Trivial Iterator together with:Those of Trivial Iterator together with: ++i, i++++i, i++ Note: after ++i is executed it is not Note: after ++i is executed it is not

guaranteed that copies of the old value of i guaranteed that copies of the old value of i be dereferenceable. be dereferenceable.

*i++*i++

Input Iterator 6Input Iterator 6

Models:Models: All pointer and STL iterators All pointer and STL iterators (except for ostream_iterator). The (except for ostream_iterator). The istream_iterator, used for traversing input istream_iterator, used for traversing input streams, is an example of an input iterator streams, is an example of an input iterator that does not belong to any of the classes that does not belong to any of the classes defined below.defined below.

Output IteratorOutput Iterator

Concept:Concept: An object is an output iterator if An object is an output iterator if it can store to its present location and be it can store to its present location and be incremented. An output iterator must give incremented. An output iterator must give write access to its location, but not write access to its location, but not necessarily read access. Also, an output necessarily read access. Also, an output iterator does not necessarily support a iterator does not necessarily support a multipass algorithm. multipass algorithm.

Output Iterator 2Output Iterator 2

Refines:Refines: Assignable Assignable Associated Types: Associated Types: Only the followingOnly the following iterator_categoryiterator_category One of the iterator tag types: One of the iterator tag types:

output_iterator_tag, forward_iterator_tag, output_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tagrandom_access_iterator_tag

Output Iterator 3Output Iterator 3

Operations: those of Assignable together Operations: those of Assignable together withwith

Dereference assignment: *x = tDereference assignment: *x = t ++x, x++++x, x++ Postincrement assignment: *x++ = tPostincrement assignment: *x++ = t

Output Iterator 4Output Iterator 4

Models:Models: front_insert_iterator, front_insert_iterator, back_insert_iterator, insert_iterator, back_insert_iterator, insert_iterator, ostream_iteratorostream_iterator

Forward IteratorForward Iterator

Concept:Concept: An object is a Forward Iterator if An object is a Forward Iterator if the iterator may be incremented and gives the iterator may be incremented and gives both read and write access (for mutable both read and write access (for mutable iterators).iterators).

Refines:Refines: Default Constructible, Input Default Constructible, Input Iterator, Output Iterator Iterator, Output Iterator

Forward Iterator 2Forward Iterator 2

Associated Types:Associated Types: Same as Input Same as Input Iterator.Iterator.

Operations:Operations: Same as Default Same as Default Constructible and Input Iterator (but not Constructible and Input Iterator (but not the restrictions of Input Iterator).the restrictions of Input Iterator).

Models:Models: Pointers, all STL container Pointers, all STL container iterators iterators

Bidirectional IteratorBidirectional Iterator

Concept:Concept: An object is a bidirectional An object is a bidirectional iterator if it allows for increments and iterator if it allows for increments and decrements. It gives both read and write decrements. It gives both read and write access (for mutable iterators). access (for mutable iterators).

Refines:Refines: Forward Iterator Forward Iterator Associated Types:Associated Types: Same as for Forward Same as for Forward

IteratorIterator

Bidirectional Iterator 2Bidirectional Iterator 2

Operations:Operations: Those of Forward Iterator Those of Forward Iterator together with --x, x--.together with --x, x--.

Invariant:Invariant: ++x; --x; or --x; ++x; are null operations++x; --x; or --x; ++x; are null operations Models:Models: Pointers, all STL container Pointers, all STL container

iterators iterators

Random Access IteratorRandom Access Iterator

Concept:Concept: An object is a Random Access An object is a Random Access Iterator if it allows arbitrary jumps and Iterator if it allows arbitrary jumps and pointer arithmetic.pointer arithmetic.

Refines:Refines: Bidirectional Iterator Bidirectional Iterator Associated Types:Associated Types: Same as for Same as for

Bidirectional Iterator.Bidirectional Iterator.

Random Access Iterator 2Random Access Iterator 2 Operations: Operations: i += n (equivalent to performing ++i n i += n (equivalent to performing ++i n

timestimes i -= n (equivalent to i += (-n) )i -= n (equivalent to i += (-n) ) i+n, n+i i+n, n+i Equivalent to X tmp = i; return tmp += n;Equivalent to X tmp = i; return tmp += n; i-n;i-n; Equivalent to X tmp = i; return tmp -= n;Equivalent to X tmp = i; return tmp -= n;

Random Access Iterator 3Random Access Iterator 3 More operations:More operations: i – ji – j Returns a number n such that i == j+nReturns a number n such that i == j+n i[n]i[n] Equivalent to *(i + n)Equivalent to *(i + n) Invariants:Invariants: If i + n is defined then i += n; i -= n; is a If i + n is defined then i += n; i -= n; is a

null operation (similarly for i – n)null operation (similarly for i – n)

Random Access Iterator 4Random Access Iterator 4

Models: Pointers and the iterators for Models: Pointers and the iterators for vector and deque containers. vector and deque containers.

Iterator AdaptorsIterator Adaptors

An iterator adaptor is a class that is a An iterator adaptor is a class that is a wrapper for an iterator.wrapper for an iterator.

Adaptors have their own concepts Adaptors have their own concepts (discussed below).(discussed below).

Reverse IteratorReverse Iterator

Concept:Concept: A reverse_iterator takes a A reverse_iterator takes a bidirectional or random access iterator and bidirectional or random access iterator and creates a new iterator that traverses in the creates a new iterator that traverses in the opposite direction of usual iteration. opposite direction of usual iteration.

Operations:Operations: *p, ++p, p++ (each performs *p, ++p, p++ (each performs a decrement), --p, p--(each performs an a decrement), --p, p--(each performs an increment).increment).

Reverse Iterator 2Reverse Iterator 2 ExampleExamplevector<int> v;vector<int> v;//Suppose we place data in v//Suppose we place data in vcopy(v.rbegin(), v.rend(), copy(v.rbegin(), v.rend(),

ostream_iterator<int>(cout," "));ostream_iterator<int>(cout," ")); This copies the data from to cout in reverse This copies the data from to cout in reverse

order. The call, v.rbegin() creates a order. The call, v.rbegin() creates a reverse_iterator that points to the last location in reverse_iterator that points to the last location in v. The call, v.rend(), points to a position one v. The call, v.rend(), points to a position one before the first location in v.before the first location in v.

Istream IteratorIstream Iterator

Concept:Concept: An istream_iterator is used for An istream_iterator is used for traversing an input stream (allowing only traversing an input stream (allowing only read access and increments). read access and increments).

Models:Models: Input Iterator Input Iterator

Ostream IteratorOstream Iterator

Concept:Concept: An ostream_iterator is used for An ostream_iterator is used for traversing an output stream (allowing only traversing an output stream (allowing only write access and decrements). write access and decrements).

Models:Models: Output Iterator Output Iterator

Back Insert IteratorBack Insert Iterator Concept:Concept: A back_insert_iterator takes a A back_insert_iterator takes a

container x and converts assignments into container x and converts assignments into x.push_back(). Frequently one uses the x.push_back(). Frequently one uses the template function back_inserter, that template function back_inserter, that returns a back_insert_iterator. returns a back_insert_iterator.

Operations:Operations: *p, ++p, p++ (all do nothing *p, ++p, p++ (all do nothing except return *this). *p = t (calls except return *this). *p = t (calls x.push_back(t), where x is the container x.push_back(t), where x is the container associated with p). associated with p).

Back Insert Iterator 2Back Insert Iterator 2

Models:Models: Output Iterator Output Iterator

Front Insert IteratorFront Insert Iterator Concept:Concept: A front_insert_iterator takes a A front_insert_iterator takes a

container x and converts assignments into container x and converts assignments into x.push_front(). Frequently one uses the x.push_front(). Frequently one uses the template function front_inserter, that template function front_inserter, that returns a front_insert_iterator. returns a front_insert_iterator.

Operations:Operations: *p, ++p, p++ (all do nothing *p, ++p, p++ (all do nothing except return *this). *p = t (calls except return *this). *p = t (calls x.push_front(t), where x is the container x.push_front(t), where x is the container associated with p). associated with p).

Front Insert Iterator 2Front Insert Iterator 2

Models:Models: Output Iterator Output Iterator

Insert IteratorInsert Iterator Concept:Concept: An insert_iterator takes a An insert_iterator takes a

container x and converts assignments into container x and converts assignments into x.insert(). Frequently one uses the x.insert(). Frequently one uses the template function inserter, that returns a template function inserter, that returns a insert_iterator. insert_iterator.

Operations:Operations: *p, ++p, p++ (all do nothing *p, ++p, p++ (all do nothing except return *this). *p = t (calls except return *this). *p = t (calls x.insert(p,t), where x is the container x.insert(p,t), where x is the container associated with p).associated with p).

Insert Iterator 2Insert Iterator 2

Models:Models: Output Iterator Output Iterator

ExampleExample Suppose we want to read in a file of Suppose we want to read in a file of

grades.grades.multiset<int> grade_set;multiset<int> grade_set;ifstream in_file("grades.dat");ifstream in_file("grades.dat");  copy(istream_iterator<int>(in_file), copy(istream_iterator<int>(in_file), istream_iterator<int>(),istream_iterator<int>(), inserter(grade_set));inserter(grade_set));

Iterator traitsIterator traits

struct input_iterator_tag {};struct input_iterator_tag {};struct output_iterator_tag {};struct output_iterator_tag {};struct forward_iterator_tagstruct forward_iterator_tag

: public input_iterator_tag {};: public input_iterator_tag {};struct bidirectional_iterator_tagstruct bidirectional_iterator_tag

: public forward_iterator_tag {};: public forward_iterator_tag {};struct random_access_iterator_tagstruct random_access_iterator_tag

: public bidirectional_iterator_tag {};: public bidirectional_iterator_tag {};

Iterator traits 2Iterator traits 2template<class Iterator>template<class Iterator>struct iterator_traits {struct iterator_traits {

typedef typename Iterator::iterator_categorytypedef typename Iterator::iterator_categoryiterator_category;iterator_category;typedef typename Iterator::value_type typedef typename Iterator::value_type value_type;value_type;typedef typename Iterator::difference_typetypedef typename Iterator::difference_type

difference_type;difference_type;typedef typename Iterator::pointer typedef typename Iterator::pointer pointer;pointer;typedef typename Iterator::reference typedef typename Iterator::reference reference;reference;

};};

Iterator traits 3Iterator traits 3

template<class T>template<class T>struct iterator_traits<T*> {struct iterator_traits<T*> {

typedef random_access_iterator_tagtypedef random_access_iterator_tagiterator_category;iterator_category;

typedef T typedef T value_type;value_type;typedef ptrdiff_t difference_type;typedef ptrdiff_t difference_type;typedef T* typedef T* pointer;pointer;typedef T& reference;typedef T& reference;

};};

Iterator traits 4Iterator traits 4

template<class T>template<class T>struct iterator_traits<const T*> {struct iterator_traits<const T*> {

typedef random_access_iterator_tagtypedef random_access_iterator_tagiterator_category;iterator_category;

typedef T typedef T value_type;value_type;typedef ptrdiff_t difference_type;typedef ptrdiff_t difference_type;typedef const T* pointer;typedef const T* pointer;typedef const T& reference;typedef const T& reference;

};};

Iterator traits 5Iterator traits 5template<class Category, class Value, template<class Category, class Value, class Distance = ptrdiff_t, class Distance = ptrdiff_t, class Pointer = Value*, class Pointer = Value*, class Reference = Value&>class Reference = Value&>struct iterator {struct iterator {

typedef Category iterator_category;typedef Category iterator_category;typedef Value value_type;typedef Value value_type;typedef Distance difference_type;typedef Distance difference_type;typedef Pointer pointer;typedef Pointer pointer;typedef Reference reference;typedef Reference reference;

};};

Iterator traits 6Iterator traits 6

template<class Value, class Distance,template<class Value, class Distance, class Pointer, class Reference>class Pointer, class Reference>struct BidirectionalIteratorstruct BidirectionalIterator: public Iterator<bidirectional_iterator_tag,: public Iterator<bidirectional_iterator_tag, Value,Distance,Pointer, Value,Distance,Pointer, Reference> {};Reference> {};

Iterator traits 7Iterator traits 7

template<class Value, class Distance,template<class Value, class Distance, class Pointer, class Reference>class Pointer, class Reference>struct RandomAccessIteratorstruct RandomAccessIterator: public Iterator<random_access_iterator_tag, : public Iterator<random_access_iterator_tag,

Value,Distance, Value,Distance, Pointer,Reference> {};Pointer,Reference> {};

Iterator traits 8Iterator traits 8

template<class Value, class Distance,template<class Value, class Distance, class Pointer, class Reference>class Pointer, class Reference>struct OutputIteratorstruct OutputIterator: public Iterator<output_iterator_tag,: public Iterator<output_iterator_tag,

Value,Distance,Value,Distance, Pointer,Reference> {};Pointer,Reference> {};

Iterator traits 9Iterator traits 9

template<class InputIter, class Distance>template<class InputIter, class Distance>void advance(InputIter &I, Distance N)void advance(InputIter &I, Distance N){{

Advance(I, N, typename Advance(I, N, typename iterator_traits<InputIter>::iterator_category());iterator_traits<InputIter>::iterator_category());

}}

Iterator traits 10Iterator traits 10

template<class InputIter, class Distance>template<class InputIter, class Distance>void Advance(InputIter &I, Distance N,void Advance(InputIter &I, Distance N,

input_iterator_tag) input_iterator_tag) {{

for( ; 0 < N; --N)for( ; 0 < N; --N)++I;++I;

}}

Iterator traits 11Iterator traits 11

template<class ForwardIter, class Distance>template<class ForwardIter, class Distance>void Advance(ForwardIter &I, Distance N,void Advance(ForwardIter &I, Distance N,

forward_iterator_tag) {forward_iterator_tag) {for( ; 0 < N; --N)for( ; 0 < N; --N)

++I;++I;}}

Iterator traits 12Iterator traits 12

template<class BidirectionalIter, class Distance>template<class BidirectionalIter, class Distance>void Advance(BidirectionalIter &I, Distance N, void Advance(BidirectionalIter &I, Distance N,

bidirectional_iterator_tag) {bidirectional_iterator_tag) {for( ; 0 < N; --N)for( ; 0 < N; --N)

++I;++I;for( ; N < 0; ++N)for( ; N < 0; ++N)

--I;--I;}}

Iterator traits 13Iterator traits 13

template<class RandomAccessIter, template<class RandomAccessIter, class Distance>class Distance>

void Advance(RandomAccessIter &I, void Advance(RandomAccessIter &I, Distance N, forward_iterator_tag) {Distance N, forward_iterator_tag) {

I += N;I += N;}}

Container conceptsContainer concepts

There are several container concepts that There are several container concepts that are used in STL.are used in STL.

There are three types of containers: There are three types of containers: general containers which are models for general containers which are models for types of iterators, sequence containers, types of iterators, sequence containers, and associative containers.and associative containers.

ContainerContainer

Concept:Concept: A Container stores other A Container stores other objects. The lifetimes of these objects are objects. The lifetimes of these objects are at most the lifetime of the Container. at most the lifetime of the Container.

Refines:Refines: Assignable Assignable Associated TypesAssociated Types X::value_type: the type of the elements of X::value_type: the type of the elements of

the container. Must be Assignable.the container. Must be Assignable.

Container 2Container 2

X::reference: behaves as a reference to X::reference: behaves as a reference to the Container’s value type (usually just the Container’s value type (usually just value_type&).value_type&).

X::const_reference: usually just const X::const_reference: usually just const value_type&value_type&

X::pointer: behaves as a pointer to the X::pointer: behaves as a pointer to the Container’s elements (usually just Container’s elements (usually just value_type*, but can be a smart pointer)value_type*, but can be a smart pointer)

Container 3Container 3

X::const_pointer: usually just const X::const_pointer: usually just const value_type*.value_type*.

X::iterator: an iterator that points to the X::iterator: an iterator that points to the Container’s elements. Must be at least an Container’s elements. Must be at least an Input Iterator.Input Iterator.

X::const_iterator: a constant iterator that X::const_iterator: a constant iterator that points to the Container’s elements.points to the Container’s elements.

Container 4Container 4

X::difference_type: a signed integral type X::difference_type: a signed integral type used to measure the distance between used to measure the distance between two of the Container’s iterators.two of the Container’s iterators.

X::size_type: an unsigned integral type X::size_type: an unsigned integral type that can represent nonnegative values of that can represent nonnegative values of the Container’s difference type.the Container’s difference type.

Container 5Container 5

Operations:Operations: copy constructor, copy constructor, assignment (if LHS is mutable), destructor, assignment (if LHS is mutable), destructor, begin(), end(), size(), max_size() (for that begin(), end(), size(), max_size() (for that type of Container), empty(), swap()type of Container), empty(), swap()

Models:Models: all STL containers. all STL containers.

Forward ContainerForward Container

Concept:Concept: A Forward Container stores A Forward Container stores elements in a definite order. These elements in a definite order. These containers support forward iterators. containers support forward iterators.

Refines:Refines: Container, Equality Comparable, Container, Equality Comparable, LessThan ComparableLessThan Comparable

Associated Types:Associated Types: same as Container, same as Container, except X::iterator must be a Forward except X::iterator must be a Forward Iterator. Iterator.

Forward Container 2Forward Container 2

Operations:Operations: Same as Container plus the Same as Container plus the following.following.

==, !=, <, >, <=, >= (the last four use a ==, !=, <, >, <=, >= (the last four use a lexicographical comparison).lexicographical comparison).

Models: All STL containers Models: All STL containers

Reversible ContainerReversible Container

Concept:Concept: A Reversible Container defines A Reversible Container defines a bidirectional iterator.a bidirectional iterator.

Refines:Refines: Forward Container Forward Container Associated Types:Associated Types: All types associated All types associated

with Container (with the requirement that with Container (with the requirement that iterators must be Bidirectional Iterators) iterators must be Bidirectional Iterators) plus the following:plus the following:

Reversible Container 2Reversible Container 2

X::reverse_iterator: A reverse iterator X::reverse_iterator: A reverse iterator adaptor that has X::iterator as its base adaptor that has X::iterator as its base iterator type. The reverse iterator maps iterator type. The reverse iterator maps operator++ to operator– (and vice versa).operator++ to operator– (and vice versa).

X::const_reverse_iterator: A reverse X::const_reverse_iterator: A reverse iterator adaptor that has X::const_iterator iterator adaptor that has X::const_iterator as its base iterator type.as its base iterator type.

Reversible Container 3Reversible Container 3

Operations:Operations: Same as Forward Container Same as Forward Container plus the following.plus the following.

rbegin() (points at last element of the rbegin() (points at last element of the container)container)

rend() (points at one before the first rend() (points at one before the first element of the container)element of the container)

Models:Models: All STL containers All STL containers

Random Access ContainerRandom Access Container

Concept:Concept: A Random Access Container A Random Access Container defines a random access iterator. defines a random access iterator.

Operations:Operations: Those of Reversible Those of Reversible Container plus element access, Container plus element access, a[n]a[n]..

Models:Models: Vectors and deques. Vectors and deques.

Vector ExampleVector Example Here is a program illustrating some ways of initializing a Here is a program illustrating some ways of initializing a

vector, together with a common error. The program below vector, together with a common error. The program below inserts a range of values into vectors v1, v2, v3, v4 by a inserts a range of values into vectors v1, v2, v3, v4 by a variety of methods.variety of methods.

   One can insert a range of the form [first, last) via:One can insert a range of the form [first, last) via:   - Constructor- Constructor vector<T> v(first,last);vector<T> v(first,last);   - Assign member function. This method deletes any data - Assign member function. This method deletes any data

previously held in the vectorpreviously held in the vector v.assign(first,last)v.assign(first,last)

Vector Example 2Vector Example 2 - Insert member function. This method does not delete - Insert member function. This method does not delete

any existing data. The following inserts the range at the any existing data. The following inserts the range at the end of vector. Any valid location could be used as the end of vector. Any valid location could be used as the insertion point.insertion point.

v.insert(v.end(), first, last);v.insert(v.end(), first, last);   - Copy algorithm. This algorithm assumes that the space - Copy algorithm. This algorithm assumes that the space

for the data being copied already exists. So the following for the data being copied already exists. So the following version is incorrect if v does not already have space version is incorrect if v does not already have space allocated to hold the data to be copied. The code will allocated to hold the data to be copied. The code will compile, but crash at run-time.compile, but crash at run-time.

copy(first, last, v.begin());copy(first, last, v.begin());

Vector Example 3Vector Example 3main()main(){{ int a[5] = {7, 3, 2, 5, 9};int a[5] = {7, 3, 2, 5, 9};   std::vector<int> v1(&a[0], &a[5]);std::vector<int> v1(&a[0], &a[5]); std::cout << "Vector 1: ";std::cout << "Vector 1: "; std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(cout," "));std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(cout," ")); cout << "\n\n";cout << "\n\n";   std::vector<int> v2;std::vector<int> v2; v2.assign(v1.begin(),v1.end());v2.assign(v1.begin(),v1.end()); cout << "Vector 2: ";cout << "Vector 2: "; std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(cout," "));std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(cout," ")); cout << "\n\n";cout << "\n\n";

Vector Example 4Vector Example 4vector<int> v3;vector<int> v3;

v3.insert(v3.end(),v2.begin(),v2.end());v3.insert(v3.end(),v2.begin(),v2.end()); cout << "Vector 3: ";cout << "Vector 3: "; copy(v3.begin(), v3.end(), ostream_iterator<int>(cout," "));copy(v3.begin(), v3.end(), ostream_iterator<int>(cout," ")); cout << "\n\n";cout << "\n\n";   vector<int> v4;vector<int> v4; //copy(v3.begin(), v3.end(), v4.begin());//copy(v3.begin(), v3.end(), v4.begin()); copy(v3.begin(), v3.end(), back_inserter(v4));copy(v3.begin(), v3.end(), back_inserter(v4)); cout << "Vector 4: ";cout << "Vector 4: "; copy(v4.begin(), v4.end(), ostream_iterator<int>(cout," "));copy(v4.begin(), v4.end(), ostream_iterator<int>(cout," ")); cout << "\n\n";cout << "\n\n";}}

Sequence ContainerSequence Container

Concept:Concept: A Sequence stores its elements A Sequence stores its elements in a linear ordering. in a linear ordering.

Refines:Refines: Forward Container, Default Forward Container, Default Constructible Constructible

Operations:Operations: Those of Forward Container Those of Forward Container plus,plus,

Default constructor, Default constructor,

Sequence Container 2Sequence Container 2

Fill constructor c(n,x) creates container Fill constructor c(n,x) creates container with n copies equal to xwith n copies equal to x

Fill constructor c(n) creates container with Fill constructor c(n) creates container with n elements initialized to default value,n elements initialized to default value,

Range constructor c(i,j). Here, i and j are Range constructor c(i,j). Here, i and j are input iterators. Creates a sequence that is input iterators. Creates a sequence that is a copy of the range [i,j).a copy of the range [i,j).

Sequence Container 3Sequence Container 3 Insert: c.insert(p,x) inserts the value x Insert: c.insert(p,x) inserts the value x

before position p. before position p. Special cases:Special cases: a.insert(a.begin(), x) inserts x before the a.insert(a.begin(), x) inserts x before the

first element of a.first element of a. a.insert(a.end(),x) inserts x after the last a.insert(a.end(),x) inserts x after the last

element of a.element of a. Note: the iterator p need not be valid after Note: the iterator p need not be valid after

the insert is performed.the insert is performed.

Sequence Container 4Sequence Container 4

Fill insert: a.insert(p, n, x) inserts n copies Fill insert: a.insert(p, n, x) inserts n copies of value x before position p.of value x before position p.

This is guaranteed to be no slower than This is guaranteed to be no slower than calling insert(p,x) n times.calling insert(p,x) n times.

Range insert: a.insert(p, i, j) inserts a copy Range insert: a.insert(p, i, j) inserts a copy of the range [i,j) before position p.of the range [i,j) before position p.

Sequence Container 5Sequence Container 5

Erase: a.erase(p) erases the element at Erase: a.erase(p) erases the element at position p.position p.

This assumes that p is dereferenceable.This assumes that p is dereferenceable. It returns an iterator to the element It returns an iterator to the element

immediately following the one removed or immediately following the one removed or else a.end() if there is no such element.else a.end() if there is no such element.

Note: erase may invalidate iterators into Note: erase may invalidate iterators into the sequence.the sequence.

Sequence Container 6Sequence Container 6

Range erase: a.erase(p,q) erases all Range erase: a.erase(p,q) erases all elements in the range [p,q).elements in the range [p,q).

The return value is an iterator pointing to The return value is an iterator pointing to the element immediately after the range the element immediately after the range that was removed or a.end() if no such that was removed or a.end() if no such element exists.element exists.

Sequence Container 7Sequence Container 7

Front: a.front() returns a reference to the Front: a.front() returns a reference to the first element in the sequence.first element in the sequence.

Assumes the sequence is not empty.Assumes the sequence is not empty. Models:Models: vector, list, deque vector, list, deque

Sequence Container 8Sequence Container 8

Can the range insertion be used to copy Can the range insertion be used to copy from a container to itself?from a container to itself?

Can the range overlap with the position of Can the range overlap with the position of the insertion?the insertion?

Consider the following example.Consider the following example.

Sequence Container 9Sequence Container 9main() {main() { std::vector<int> v;std::vector<int> v; int a[ ] = {5,2,3,4,6};int a[ ] = {5,2,3,4,6};

v.insert(v.end(),&a[0],&a[5]);v.insert(v.end(),&a[0],&a[5]);

std::vector<int>::iterator p,i;std::vector<int>::iterator p,i; p = find(v.begin(),v.end(),2);p = find(v.begin(),v.end(),2);

v.insert(p,v.begin(),v.end());v.insert(p,v.begin(),v.end()); copy(v.begin(),v.end(),copy(v.begin(),v.end(), std::ostream_iterator<int>(std::cout, " "));std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n';std::cout << '\n';}}

Sequence Container 10Sequence Container 10

The output isThe output is5 5 2 3 4 6 2 3 4 65 5 2 3 4 6 2 3 4 6

How does the insert function work?How does the insert function work?

vector::insertvector::insert

template<class InputIter>template<class InputIter>void insert(iterator p, InputIter F, InputIter L)void insert(iterator p, InputIter F, InputIter L){{

size_type M = F - L;size_type M = F - L;size_type N = capacity();size_type N = capacity();

vector::insert 2vector::insert 2

if (M == 0)if (M == 0);;

else if (max_size() < M + size())else if (max_size() < M + size())throw length_error("vector too long");throw length_error("vector too long");

vector::insert 3vector::insert 3else if (N < size() + M) {else if (N < size() + M) {

N = (max_size() < N + N/2) ? N + N/2 : size() + N = (max_size() < N + N/2) ? N + N/2 : size() + M;M;

pointer S = Mybase::Alval.allocate(N, (void *) pointer S = Mybase::Alval.allocate(N, (void *) 0);0);

pointer Q;pointer Q;Q = copy(begin(),P,S);Q = copy(begin(),P,S);Q = copy(F,L,Q);Q = copy(F,L,Q);copy(P,end(),Q);copy(P,end(),Q);

}}

vector::insert 4vector::insert 4

else if ( (size_type) (end() - P) < M ) {else if ( (size_type) (end() - P) < M ) {copy(P, end(), P+M);copy(P, end(), P+M);

InputIter Mid = F;InputIter Mid = F;advance(Mid, end() - P);advance(Mid, end() - P);

copy(Mid, L, end());copy(Mid, L, end());copy(F, Mid, P);copy(F, Mid, P);

}}

vector::insert 5vector::insert 5

else if ( 0 < M ) {else if ( 0 < M ) {iterator Old_end() = end();iterator Old_end() = end();copy(Old_end - M, Old_end, end());copy(Old_end - M, Old_end, end());copy_backward(P, Old_end - M, copy_backward(P, Old_end - M,

Old_end);Old_end);copy(F,L,P);copy(F,L,P);

}}}}

GCC vector::insertGCC vector::insert

template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc> template<typename _ForwardIterator>template<typename _ForwardIterator>

voidvoid vector<_Tp,_Alloc>::vector<_Tp,_Alloc>:: _M_range_insert(iterator __position,_ForwardIterator _M_range_insert(iterator __position,_ForwardIterator

__first, _ForwardIterator __last, forward_iterator_tag)__first, _ForwardIterator __last, forward_iterator_tag){{

GCC vector::insert 2GCC vector::insert 2

if (__first != __last)if (__first != __last) {{ size_type __n = std::distance(__first, __last);size_type __n = std::distance(__first, __last); if (size_type(this->_M_impl._M_end_of_storage – if (size_type(this->_M_impl._M_end_of_storage –

this->_M_impl._M_finish) >= __n)this->_M_impl._M_finish) >= __n) {{

GCC vector::insert 3GCC vector::insert 3 const size_type __elems_after = end() - __position;const size_type __elems_after = end() - __position;

iterator __old_finish(this->_M_impl._M_finish);iterator __old_finish(this->_M_impl._M_finish); if (__elems_after > __n)if (__elems_after > __n) { { std::uninitialized_copy(this->_M_impl._M_finish - std::uninitialized_copy(this->_M_impl._M_finish -

__n, this->_M_impl._M_finish, this->_M_impl._M_finish);__n, this->_M_impl._M_finish, this->_M_impl._M_finish);

this->_M_impl._M_finish += __n;this->_M_impl._M_finish += __n; std::copy_backward(__position, __old_finish - __n, std::copy_backward(__position, __old_finish - __n,

__old_finish);__old_finish); std::copy(__first, __last, __position);std::copy(__first, __last, __position); } }

GCC vector::insert 4GCC vector::insert 4 elseelse {{ _ForwardIterator __mid = __first;_ForwardIterator __mid = __first; std::advance(__mid, __elems_after);std::advance(__mid, __elems_after); std::uninitialized_copy(__mid, __last, std::uninitialized_copy(__mid, __last,

this->_M_impl._M_finish);this->_M_impl._M_finish); this->_M_impl._M_finish += __elems_after;this->_M_impl._M_finish += __elems_after; std::copy(__first, __mid, __position);std::copy(__first, __mid, __position); }} }}

GCC vector::insert 5GCC vector::insert 5elseelse{{ const size_type __old_size = size();const size_type __old_size = size(); const size_type __len = __old_size + const size_type __len = __old_size +

std::max(__old_size, __n);std::max(__old_size, __n); iterator __new_start(this->_M_allocate(__len));iterator __new_start(this->_M_allocate(__len)); iterator __new_finish(__new_start);iterator __new_finish(__new_start); trytry {{ __new_finish = __new_finish =

std::uninitialized_copy(iterator(this->_M_impl._M_start),std::uninitialized_copy(iterator(this->_M_impl._M_start), __position, __new_start);__position, __new_start);

GCC vector::insert 6GCC vector::insert 6 __new_finish = __new_finish =

std::uninitialized_copy(__first, __last, __new_finish);std::uninitialized_copy(__first, __last, __new_finish);

__new_finish = std::uninitialized_copy(__position,__new_finish = std::uninitialized_copy(__position, iterator(this->_M_impl._M_finish), __new_finish);iterator(this->_M_impl._M_finish), __new_finish);}}catch(...)catch(...){{ std::_Destroy(__new_start,__new_finish);std::_Destroy(__new_start,__new_finish); _M_deallocate(__new_start.base(), __len);_M_deallocate(__new_start.base(), __len); __throw_exception_again;__throw_exception_again;}}

GCC vector::insert 7GCC vector::insert 7std::_Destroy(this->_M_impl._M_start, std::_Destroy(this->_M_impl._M_start,

this->_M_impl._M_finish);this->_M_impl._M_finish);_M_deallocate(this->_M_impl._M_start,_M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage – this->_M_impl._M_end_of_storage –

this->_M_impl._M_start);this->_M_impl._M_start);this->_M_impl._M_start = __new_start.base();this->_M_impl._M_start = __new_start.base();this->_M_impl._M_finish = __new_finish.base();this->_M_impl._M_finish = __new_finish.base();this->_M_impl._M_end_of_storage = this->_M_impl._M_end_of_storage =

__new_start.base() + __len;__new_start.base() + __len; }} }} }}

Is this legal?Is this legal?template<class T>template<class T>class my_sequence {class my_sequence {private:private:

//Some data //Some data public:public:

//Assume the appropriate iterator has been defined//Assume the appropriate iterator has been defined

//Consider the following insert functions//Consider the following insert functionsvoid insert(iterator p, size_type n, const T &t) void insert(iterator p, size_type n, const T &t) { std::cout << "insert(p,n,t)\n"; }{ std::cout << "insert(p,n,t)\n"; }

template<class InputIterator>template<class InputIterator>void insert(iterator p, InputIterator first, InputIterator last) void insert(iterator p, InputIterator first, InputIterator last) { std::cout << "insert(p,first,last)\n"; }{ std::cout << "insert(p,first,last)\n"; }

};};

Example 2Example 2

main() {main() {my_sequence<int> m;my_sequence<int> m;

m.insert(m.begin(), 100, 5);m.insert(m.begin(), 100, 5);return 0;return 0;

}}

This is legal. But not what one might expect. The output is:

insert(p,first,last)insert(p,first,last)

In other words, the compiler decides that In other words, the compiler decides that

m.insert(m.begin(), 100, 5);m.insert(m.begin(), 100, 5);

best fits the second insert function (whereas we best fits the second insert function (whereas we expected to match the first).expected to match the first).

Why is that?

void insert(iterator p, InputIterator first, InputIterator last) void insert(iterator p, InputIterator first, InputIterator last)

Is an exact match because the last two arguments for m.insert(m.begin(), 100, 5)m.insert(m.begin(), 100, 5) are are both ints. both ints.

So the compiler matches the type InputIterator to So the compiler matches the type InputIterator to int.int.

But in the other insert function,

void insert(iterator p, size_type n, const T &t)void insert(iterator p, size_type n, const T &t)

The compiler matches T to be an int. Usually The compiler matches T to be an int. Usually size_t will be a typedef for unsigned int. So that size_t will be a typedef for unsigned int. So that m.insert(m.begin(), 100, 5)m.insert(m.begin(), 100, 5) is not an exact match for this version of insert.

Where did we go wrong?Where did we go wrong? This is actually a very difficult problem to This is actually a very difficult problem to

solve. There is no simple way to get the solve. There is no simple way to get the compiler to match the correct version of compiler to match the correct version of insert.insert.

One could specialize the class for the case One could specialize the class for the case when T is an int.when T is an int.

One could overload the first insert function One could overload the first insert function for cases where the second argument is for cases where the second argument is an int, a long, etc.an int, a long, etc.

Where did we go wrong? 2Where did we go wrong? 2

These methods are cumbersome (one has These methods are cumbersome (one has to write a lot of extra code that looks to write a lot of extra code that looks exactly the same).exactly the same).

Another solution is to test if the parameter Another solution is to test if the parameter type InputIter is an integral type. There is a type InputIter is an integral type. There is a static member of the class numeric_limits static member of the class numeric_limits called is_integer. called is_integer.

Where did we go wrong? 3Where did we go wrong? 3 How does that work? The class How does that work? The class

numeric_limits looks like:numeric_limits looks like:template<class T>template<class T>class numeric_limits {class numeric_limits {public:public:

static const bool is_integer = false;static const bool is_integer = false;//…//…};};

Where did we go wrong? 4Where did we go wrong? 4

There are specialized versions of There are specialized versions of numeric_limits for each integral type. numeric_limits for each integral type.

In each of these specialized classes In each of these specialized classes is_integer is set equal to true.is_integer is set equal to true.

Corrected versionCorrected version#include<iostream>#include<iostream>#include<limits>#include<limits>

template<bool B>template<bool B>struct int_test { };struct int_test { };

template<class T>template<class T>class my_sequence {class my_sequence {public:public: typedef T* iterator;typedef T* iterator;

private:private: //Some data//Some data

Corrected version 2Corrected version 2private:private:

void fill_insert(iterator p, unsigned int n, void fill_insert(iterator p, unsigned int n, const T &t)const T &t)

{ std::cout << "insert(p,n,t)\n"; }{ std::cout << "insert(p,n,t)\n"; }

template<class InputIter>template<class InputIter> void range_insert(iterator p, InputIter first,void range_insert(iterator p, InputIter first,

InputIter last)InputIter last) { std::cout << "insert(p,first,last)\n"; }{ std::cout << "insert(p,first,last)\n"; }

Corrected version 3Corrected version 3 template<class Integral>template<class Integral> void insert(iterator p, Integral n, Integral t,void insert(iterator p, Integral n, Integral t,

int_test<true>) {int_test<true>) { fill_insert(p,n,t);fill_insert(p,n,t); }}

template<class InputIter>template<class InputIter> void insert(iterator p, InputIter f, InputIter l,void insert(iterator p, InputIter f, InputIter l,

int_test<false>) {int_test<false>) { range_insert(p,f,l);range_insert(p,f,l); }}

Corrected version 4Corrected version 4public:public: //Consider the following insert functions//Consider the following insert functions void insert(iterator p, unsigned int n, const T &t) {void insert(iterator p, unsigned int n, const T &t) { fill_insert(p,n,t);fill_insert(p,n,t); }}

template<class InputIter>template<class InputIter> void insert(iterator p, InputIter first, InputIter last)void insert(iterator p, InputIter first, InputIter last) {{ insert(p,first,last,insert(p,first,last, int_test<std::numeric_limits<InputIter>::is_integer>());int_test<std::numeric_limits<InputIter>::is_integer>()); }}};};

Corrected version 5Corrected version 5

main() {main() { my_sequence<int> m;my_sequence<int> m; m.insert(m.begin(), 100, 5);m.insert(m.begin(), 100, 5); return 0;return 0;}}//Output is now//Output is nowinsert(p,n,t)insert(p,n,t)

Front Insertion SequenceFront Insertion Sequence

Concept:Concept: A container is a Front Insertion A container is a Front Insertion Sequence if it allows insertion/deletion of Sequence if it allows insertion/deletion of an element at the beginning of a sequence an element at the beginning of a sequence in constant time. in constant time.

Refines:Refines: Sequence Sequence Operations:Operations: In addition to the Sequence In addition to the Sequence

operations we have the following:operations we have the following:

Front Insertion Sequence 2Front Insertion Sequence 2

Push front: a.push_front(t) is equivalent to Push front: a.push_front(t) is equivalent to a.insert(a.begin(),t)a.insert(a.begin(),t)

Pop front: a.pop_front() is equivalent to Pop front: a.pop_front() is equivalent to a.erase(a.begin(),t). Has a void return.a.erase(a.begin(),t). Has a void return.

Note: Note: push_frontpush_front followed by followed by pop_frontpop_front is a null operation. is a null operation.

Back Insertion SequenceBack Insertion Sequence

Concept:Concept: A container is a Back Insertion A container is a Back Insertion Sequence if it allows insertion/deletion of Sequence if it allows insertion/deletion of an element at the end of a sequence in an element at the end of a sequence in constant time. constant time.

Refines:Refines: Sequence Sequence Operations:Operations: In addition to the Sequence In addition to the Sequence

operations we have the following:operations we have the following:

Back Insertion Sequence 2Back Insertion Sequence 2

Back: a.back() returns a reference or Back: a.back() returns a reference or const_reference to the final element of const_reference to the final element of aa (depending on whether the container (depending on whether the container aa is is const).const).

Push back: a.push_back(t) is equivalent to Push back: a.push_back(t) is equivalent to a.insert(a.end(), t)a.insert(a.end(), t)

Pop back: a.pop_back() is equivalent to Pop back: a.pop_back() is equivalent to a.erase(--a.end()). Has a void return.a.erase(--a.end()). Has a void return.

Associative ContainerAssociative Container Concept:Concept: An Associative Container accesses An Associative Container accesses

elements in the container based on keys. Keys elements in the container based on keys. Keys are kept in a sorted order (where the user may are kept in a sorted order (where the user may supply the sorting criterion). The keys and supply the sorting criterion). The keys and associated values are stored with a tree data associated values are stored with a tree data structure (in particular, a red-black tree is the structure (in particular, a red-black tree is the usual implementation). Since the sorted order of usual implementation). Since the sorted order of the keys is an invariant for this container, the keys is an invariant for this container, insertions are not allowed to specify the position insertions are not allowed to specify the position of insertion. of insertion.

Associative Container 2Associative Container 2

Refines:Refines: Forward Container, Default Forward Container, Default Constructible Constructible

Associated Types:Associated Types: those of Forward those of Forward Container together with,Container together with,

X::key_type the type of the key associated X::key_type the type of the key associated with X::value_typewith X::value_type

Associative Container 3Associative Container 3

Operations:Operations: Same as Forward Container Same as Forward Container together with the followingtogether with the following

Default ConstructorDefault Constructor Find: a.find(k) returns an iterator pointing Find: a.find(k) returns an iterator pointing

to an element whose key is k. Returns to an element whose key is k. Returns a.end() if key not found.a.end() if key not found.

Count: a.count(k) returns the number of Count: a.count(k) returns the number of elements whose key is k.elements whose key is k.

Associative Container 4Associative Container 4 Equal Range: a.equal_range(k) returns a Equal Range: a.equal_range(k) returns a

pair P of iterators with key equal to k. The pair P of iterators with key equal to k. The range is [P.first,P.second).range is [P.first,P.second).

Erase key: a.erase_key(k) erase all Erase key: a.erase_key(k) erase all elements whose key is k. elements whose key is k.

Erase element: a.erase(p) erases the Erase element: a.erase(p) erases the element pointed to by p.element pointed to by p.

Erase range: a.erase(i,j) erases the Erase range: a.erase(i,j) erases the elements in the range [i,j)elements in the range [i,j)

Associative Container 5Associative Container 5

Models:Models: set, multiset, map, multimap set, multiset, map, multimap

Associative Container FAQAssociative Container FAQ

What does end() return for an associative What does end() return for an associative container?container?

end() returns an iterator to a special tree end() returns an iterator to a special tree node Head.node Head.

This node contains no data, its left pointer This node contains no data, its left pointer points at the smallest element in the tree, points at the smallest element in the tree, its right pointer points at the largest its right pointer points at the largest element in the tree, its parent is the root.element in the tree, its parent is the root.

Associative Container FAQ 2Associative Container FAQ 2

How do you increment an iterator for an How do you increment an iterator for an Associative Container?Associative Container?

Such iterators internally store a node Such iterators internally store a node pointer Ptr.pointer Ptr.

void increment()void increment(){{

if ( Isnil(Ptr) )if ( Isnil(Ptr) );;

else if ( !Isnil(Right(Ptr)) )else if ( !Isnil(Right(Ptr)) )Ptr = Min(Right(Ptr));Ptr = Min(Right(Ptr));

else {else {Nodeptr P;Nodeptr P;while ( !Isnil(P = Parent(Ptr)) while ( !Isnil(P = Parent(Ptr))

&& Ptr == Right(P) )&& Ptr == Right(P) )Ptr = P;Ptr = P;

Ptr = P;Ptr = P;}}

}}

Associative Container FAQ 3Associative Container FAQ 3

How do lower_bound(), upper_bound() How do lower_bound(), upper_bound() and equal_range() work?and equal_range() work?

Lower_bound finds the first of an Lower_bound finds the first of an equivalent sequence of keys.equivalent sequence of keys.

Upper_bound finds the first element past Upper_bound finds the first element past an equivalent sequence of keys.an equivalent sequence of keys.

Equal_range returns the pair of iterators, Equal_range returns the pair of iterators, lower_bound and upper_bound.lower_bound and upper_bound.

Nodeptr Lbound(const key_type &k) const{

Nodeptr X = Root();Nodeptr Y = Head;

while( !Isnil(X) )if( comp(Key(X),k) )

X = Right(X);else {

Y = X;X = Left(X);

}return Y;

}

Nodeptr Ubound(const key_type &k) const{

Nodeptr X = Root();Nodeptr Y = Head;

while( !Isnil(X) )if( comp(k,Key(X)) ) {

Y = X;X = Left(X);

}else

X = Right(X);return Y;

}

Unique Associative ContainerUnique Associative Container

Concept:Concept: A Unique Associative Container A Unique Associative Container is an Associative Container with the is an Associative Container with the property that each key in the container is property that each key in the container is unique. An element doesn’t get inserted unique. An element doesn’t get inserted into a container if its key is already into a container if its key is already present.present.

Refines:Refines: Associative Container Associative Container

Unique Associative Container 2Unique Associative Container 2

Operations:Operations: Same as Associative Same as Associative Container plus,Container plus,

Range constructor: X a(i,j) creates an Range constructor: X a(i,j) creates an associative container that includes all associative container that includes all elements in [i,j) that have unique keys.elements in [i,j) that have unique keys.

Unique Associative Container 3Unique Associative Container 3

Insert element: a.insert(t) inserts the Insert element: a.insert(t) inserts the element if and only if t’s key is not already element if and only if t’s key is not already in container. Returns pair<iterator,bool>. If in container. Returns pair<iterator,bool>. If element is already in container, iterator element is already in container, iterator points to an element in the container with points to an element in the container with that key and the bool is false. If the that key and the bool is false. If the element not in the container then the element not in the container then the iterator points to where the element is iterator points to where the element is inserted and the bool is true.inserted and the bool is true.

Unique Associative Container 4Unique Associative Container 4

Insert range: a.insert(i,j) inserts all the Insert range: a.insert(i,j) inserts all the elements in [i,j) whose key is not already elements in [i,j) whose key is not already in the container.in the container.

Models:Models: set, map set, map

Multiple Associative ContainerMultiple Associative Container

Concept:Concept: A Multiple Associative Container A Multiple Associative Container is an Associative Container that may is an Associative Container that may contain more than one element with the contain more than one element with the same key.same key.

Refines:Refines: Associative Container Associative Container Operations:Operations: Those of Associative Those of Associative

Container together with the following,Container together with the following,

Multiple Associative Container 2Multiple Associative Container 2

Range constructor: X a(i,j) creates an Range constructor: X a(i,j) creates an associative container that contains all the associative container that contains all the elements in the range [i,j).elements in the range [i,j).

Insert element: a.insert(t) inserts t and Insert element: a.insert(t) inserts t and returns a pointer to the newly inserted returns a pointer to the newly inserted element.element.

Insert range: a.insert(i,j) inserts all the Insert range: a.insert(i,j) inserts all the elements in the range [i,j).elements in the range [i,j).

Multiple Associative Container 3Multiple Associative Container 3

Models:Models: multiset, multimap multiset, multimap

Simple Associative ContainerSimple Associative Container

Concept:Concept: A Simple Associative Container A Simple Associative Container is an Associative Container whose is an Associative Container whose elements are their own keys. A value elements are their own keys. A value stored in such a container is just a key, not stored in such a container is just a key, not a key plus additional data.a key plus additional data.

Refines:Refines: Associative Container Associative Container

Simple Associative Container 2Simple Associative Container 2 Associated Types:Associated Types: Those of Associative Those of Associative

Container together with:Container together with: X::iterator. Mutable iterators are not X::iterator. Mutable iterators are not

allowed for Simple Associative Containers. allowed for Simple Associative Containers. Both X::iterator and X::const_iterator must Both X::iterator and X::const_iterator must have the same behavior.have the same behavior.

Invariant:Invariant: Elements are immutable. They Elements are immutable. They cannot be modified in place (but can be cannot be modified in place (but can be removed).removed).

Simple Associative Container 3Simple Associative Container 3

Models:Models: set and multiset. set and multiset.

Pair Associative ContainerPair Associative Container Concept:Concept: A Pair Associative Container A Pair Associative Container

associates a key with some other object.associates a key with some other object. Refines:Refines: Associative Container Associative Container Associated Types:Associated Types: Those of Associative Those of Associative

Container together withContainer together with X::key_type the type of an element’s key.X::key_type the type of an element’s key. X::mapped_type the type of an element’s X::mapped_type the type of an element’s

data. The container associates keys and data. The container associates keys and values of type mapped_type.values of type mapped_type.

Pair Associative Container 2Pair Associative Container 2

X::value_type the type of object stored in X::value_type the type of object stored in the container. The value type is the container. The value type is pair<const key_type, mapped_type>. Note pair<const key_type, mapped_type>. Note the use of const key_type. This happens the use of const key_type. This happens because the keys in a Pair Associative because the keys in a Pair Associative Container are immutable. The Container are immutable. The mapped_type part of an element may be mapped_type part of an element may be modified but not the key.modified but not the key.

Pair Associative Container 3Pair Associative Container 3

X::iterator. A Pair Associative Container X::iterator. A Pair Associative Container cannot provide mutable iterators. This is cannot provide mutable iterators. This is because the value type of a mutable because the value type of a mutable iterator must be Assignable and iterator must be Assignable and pair<const key_type, mapped_type> is not pair<const key_type, mapped_type> is not Assignable. However iterators are not Assignable. However iterators are not constant since you are allowed to have constant since you are allowed to have expressions such as i->second = val.expressions such as i->second = val.

Pair Associative Container 4Pair Associative Container 4

Models:Models: map and multimap map and multimap

Sorted Associative ContainerSorted Associative Container

Concept:Concept: A Sorted Associative Container A Sorted Associative Container sorts elements by key, using a Strict Weak sorts elements by key, using a Strict Weak Ordering.Ordering.

Refines:Refines: Associative Container and Associative Container and Reversible Container.Reversible Container.

Associated Types:Associated Types: Those of Associative Those of Associative and Reversible Container together with the and Reversible Container together with the following:following:

Sorted Associative Container 2Sorted Associative Container 2 X::key_compare is a function object type. X::key_compare is a function object type.

It uses a Strict Weak Ordering to compare It uses a Strict Weak Ordering to compare keys. It takes two arguments of type keys. It takes two arguments of type X::key_type and returns a bool.X::key_type and returns a bool.

X::value_compare is a function object that X::value_compare is a function object that compares two objects of value_type by compares two objects of value_type by passing the keys associated with these passing the keys associated with these objects to a function object of type objects to a function object of type key_compare.key_compare.

Sorted Associative Container 3Sorted Associative Container 3 Operations:Operations: Those of Associative Those of Associative

Container and Reversible Container Container and Reversible Container together with:together with:

Default constructor: X() creates an empty Default constructor: X() creates an empty container using key_compare() as the container using key_compare() as the comparison function.comparison function.

Default constructor with comparison: X(c) Default constructor with comparison: X(c) creates an empty container with creates an empty container with comparison function c.comparison function c.

Sorted Associative Container 4Sorted Associative Container 4

Range constructor: X(i,j) is equivalent toRange constructor: X(i,j) is equivalent toX a;X a;a.insert(i,j);a.insert(i,j);

Range constructor with comparison: Range constructor with comparison: X(i,j,c) is equivalent toX(i,j,c) is equivalent to

X a(c);X a(c);a.insert(i,j);a.insert(i,j);

Sorted Associative Container 5Sorted Associative Container 5

Key comparison: a.key_comp() returns a’s Key comparison: a.key_comp() returns a’s key comparison object.key comparison object.

Value comparison: a.value_comp() returns Value comparison: a.value_comp() returns a’s value comparison object.a’s value comparison object.

Lower bound: a.lower_bound(k) returns Lower bound: a.lower_bound(k) returns an iterator to the first element whose key an iterator to the first element whose key is not less than k. It returns a.end() if no is not less than k. It returns a.end() if no such element is present. such element is present.

Sorted Associative Container 6Sorted Associative Container 6

Upper bound: a.upper_bound(k) returns Upper bound: a.upper_bound(k) returns an iterator to the first element whose key an iterator to the first element whose key is greater than k. It returns a.end() if no is greater than k. It returns a.end() if no such element exists.such element exists.

Sorted Associative Container 7Sorted Associative Container 7

Equal range: a.equal_range(k) returns a Equal range: a.equal_range(k) returns a pair P such that P.first is a.lower_bound(k) pair P such that P.first is a.lower_bound(k) and P.second is a.upper_bound(k). If there and P.second is a.upper_bound(k). If there are no elements equal to k then an empty are no elements equal to k then an empty range is returned that indicates the range is returned that indicates the position where those elements would have position where those elements would have been if they did exist. All elements with been if they did exist. All elements with key k will be contained in the range key k will be contained in the range [P.first, P.second).[P.first, P.second).

Equal range exampleEqual range example#include <iostream>#include <iostream>#include <set>#include <set>#include <algorithm>#include <algorithm>#include <iterator>#include <iterator>#include <utility>#include <utility>

main() {main() { std::multiset<int> s;std::multiset<int> s;

s.insert(5);s.insert(5); s.insert(3);s.insert(3); s.insert(12);s.insert(12); s.insert(6);s.insert(6); s.insert(6);s.insert(6); s.insert(10);s.insert(10);

Equal range example 2Equal range example 2

std::copy(s.begin(), s.end(), std::copy(s.begin(), s.end(), std::ostream_iterator<int>(std::cout, " "));std::ostream_iterator<int>(std::cout, " "));std::cout << '\n';std::cout << '\n'; typedef std::multiset<int>::const_iterator CI;typedef std::multiset<int>::const_iterator CI;

Equal range example 3Equal range example 3

std::pair<CI,CI> pi = s.equal_range(6);std::pair<CI,CI> pi = s.equal_range(6);

std::copy(pi.first, pi.second,std::copy(pi.first, pi.second, std::ostream_iterator<int>(std::cout, " "));std::ostream_iterator<int>(std::cout, " "));std::cout << '\n';std::cout << '\n';

Equal range example 4Equal range example 4

pi = s.equal_range(11);pi = s.equal_range(11);if (pi.first == s.end())if (pi.first == s.end()) std::cout << "equal_range returned end()\n";std::cout << "equal_range returned end()\n";if (pi.second == s.end())if (pi.second == s.end()) std::cout << "equal_range returned end()\n";std::cout << "equal_range returned end()\n";std::cout << "equal_range.first = " std::cout << "equal_range.first = " << *pi.first << '\n';<< *pi.first << '\n';std::cout << "equal_range.second = " std::cout << "equal_range.second = " << *pi.second << '\n';<< *pi.second << '\n';

Equal range example 5Equal range example 5

std::copy(pi.first, pi.second,std::copy(pi.first, pi.second, std::ostream_iterator<int>(std::cout, " "));std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n';std::cout << '\n'; return 0;return 0;}}

Equal range example 6Equal range example 6

OutputOutput

3 5 6 6 10 12 3 5 6 6 10 12 6 6 6 6 equal_range.first = 12equal_range.first = 12equal_range.second = 12equal_range.second = 12

ExampleExample

Here is a small music database. We will Here is a small music database. We will load the database and then do a simple load the database and then do a simple query, “Print out all songs sung by Billie query, “Print out all songs sung by Billie Holiday in the database.”Holiday in the database.”

ArtistArtist SongSongBillie HolidayBillie Holiday Mean to MeMean to MeBillie HolidayBillie Holiday SummertimeSummertimeBillie HolidayBillie Holiday I Can’t Get StartedI Can’t Get StartedBix BeiderbeckeBix Beiderbecke In a MistIn a MistBix BeiderbeckeBix Beiderbecke Singin’ the BluesSingin’ the BluesRuth EttingRuth Etting Singin’ the BluesSingin’ the BluesBunny BeriganBunny Berigan I Can’t Get StartedI Can’t Get StartedLouis ArmstrongLouis Armstrong ChinatownChinatownLouis ArmstrongLouis Armstrong StardustStardustJack JenneyJack Jenney StardustStardust

#include<iostream>#include <map>#include <string>

using namespace std;

typedef string artist;typedef string song;typedef multimap<artist,song>::iterator

music_iterator; main(){ multimap<artist,song> music;

music.insert(make_pair("Billie Holiday","Mean to Me"));

music.insert(make_pair("Billie Holiday","Summertime"));

music.insert(make_pair("Billie Holiday","I Can\'t Get Started"));

music.insert(make_pair("Bix Beiderbecke", "Singin\' the Blues"));

music.insert(make_pair("Bix Beiderbecke","In a Mist"));

music.insert(make_pair("Ruth Etting", "Singin\' the Blues"));

music.insert(make_pair("Bunny Berigan","I Can\'t Get Started"));

music.insert(make_pair("Louis Armstrong", "West End Blues"));

music.insert(make_pair("Louis Armstrong", "Stardust"));

music.insert(make_pair("Louis Armstrong", "Chinatown"));

music.insert(make_pair("Jack Jenney", "Stardust"));music.insert(make_pair("Sidney Bechet",

"Summertime"));music.insert(make_pair("Sidney Bechet",

"Wild Man Blues"));music.insert(make_pair("Cootie Williams",

"West End Blues"));

//Find songs by Billie Holidaypair<music_iterator,music_iterator> p =

music.equal_range("Billie Holiday"); //Print out songs by Billie Holidaycout << "Songs by Billie Holiday\n";

for(music_iterator i = p.first, i != p.second; i++) cout << i->second << '\n'; return 0;}

OUTPUT

Songs by Billie HolidayMean to MeSummertimeI Can't Get Started

AllocatorAllocator

Concept:Concept: Manages the details of memory Manages the details of memory allocation and deallocation.allocation and deallocation.

Refines:Refines: Equality Comparable and Default Equality Comparable and Default Constructible.Constructible.

Associated Types:Associated Types: X::value_type the type that the allocator X::value_type the type that the allocator

managesmanages

Allocator 2Allocator 2

X::pointer is a pointer (not necessarily a X::pointer is a pointer (not necessarily a built-in pointer type) to X::value_type. The built-in pointer type) to X::value_type. The pointer type must be convertible to pointer type must be convertible to const_pointer, void*, and value_type*.const_pointer, void*, and value_type*.

X::const_pointer is a const pointer to X::const_pointer is a const pointer to X::value_type.X::value_type.

X::reference is a reference to X::reference is a reference to X::value_type (must be X::value_type&).X::value_type (must be X::value_type&).

Allocator 3Allocator 3 X::const_reference is a const reference to X::const_reference is a const reference to

X::value_type (must be const X::value_type (must be const X::value_type&).X::value_type&).

X::difference_type is a signed integral type X::difference_type is a signed integral type that represents the difference of two that represents the difference of two values of type X::pointer.values of type X::pointer.

X::size_type is an unsigned integral type X::size_type is an unsigned integral type that can represent any non-negative value that can represent any non-negative value of type X::difference_type.of type X::difference_type.

Allocator 4Allocator 4

X::rebind<U>::other is an allocator whose X::rebind<U>::other is an allocator whose type is U.type is U.

Operations:Operations: Default constructor: X() creates a default Default constructor: X() creates a default

allocator.allocator. Copy constructor: X b(a) creates a copy of Copy constructor: X b(a) creates a copy of

a (and compares equal to a).a (and compares equal to a).

Allocator 5Allocator 5 Generalized copy constructor: X a(y) Generalized copy constructor: X a(y)

creates a copy of y, an Allocator of value creates a copy of y, an Allocator of value type U.type U.

Comparison: a == b returns true if and Comparison: a == b returns true if and only if the storage allocated by a can be only if the storage allocated by a can be deallocated using b and vice versa.deallocated using b and vice versa.

Allocate: a.allocate(n) allocates n*sizeof(T) Allocate: a.allocate(n) allocates n*sizeof(T) bytes and returns a pointer to an bytes and returns a pointer to an uninitialized block of memory.uninitialized block of memory.

Allocator 6Allocator 6 Allocate with hint: a.allocate(n,p) allocates Allocate with hint: a.allocate(n,p) allocates

n*sizeof(T) bytes. The pointer p is a hint to n*sizeof(T) bytes. The pointer p is a hint to where the memory may be allocated (the where the memory may be allocated (the hint may be simply ignored). Returns a hint may be simply ignored). Returns a pointer to an uninitialized block of memory.pointer to an uninitialized block of memory.

Deallocate: a.deallocate(p, n) frees the Deallocate: a.deallocate(p, n) frees the memory for n objects of type T stored at memory for n objects of type T stored at location p. The pointer p must have been location p. The pointer p must have been obtained from a previous call to allocate.obtained from a previous call to allocate.

Allocator 7Allocator 7

Maximum size: a.max_size returns the Maximum size: a.max_size returns the maximum number of elements that may be maximum number of elements that may be passed as the first argument to allocate.passed as the first argument to allocate.

Construct: a.construct(p, val) constructs Construct: a.construct(p, val) constructs an object of type T at position p. an object of type T at position p. Equivalent to the placement new operator Equivalent to the placement new operator new( (void *) p) T(val). new( (void *) p) T(val).

Allocator 8Allocator 8

Destroy: a.destroy(p) destroys the object Destroy: a.destroy(p) destroys the object pointed to by p. Equivalent to pointed to by p. Equivalent to ( (T*) p) -> ~T()( (T*) p) -> ~T()

Address: a.address(t) returns of object t (in Address: a.address(t) returns of object t (in the form of a pointer or const pointer)the form of a pointer or const pointer)

Container AdaptorsContainer Adaptors

A container adaptor is a class that provide A container adaptor is a class that provide a limited number of container operations.a limited number of container operations.

There are three container adaptors in STL: There are three container adaptors in STL: stack, queue, and priority queue.stack, queue, and priority queue.

These classes are implemented in terms These classes are implemented in terms of underlying containers.of underlying containers.

StackStack Concept:Concept: A stack adapts a sequence container A stack adapts a sequence container

(deque by default). It permits insertion, deletion, (deque by default). It permits insertion, deletion, or inspection only at one end of the sequence or inspection only at one end of the sequence (designated the top of the stack). Stacks do not (designated the top of the stack). Stacks do not have iterators.have iterators.

Template parameters:Template parameters: stack<T,C>. Here T is stack<T,C>. Here T is the type of element stored in stack and C is the the type of element stored in stack and C is the underlying sequence container.underlying sequence container.

Stack 2Stack 2

MembersMembers stack::value_type is the type of object stack::value_type is the type of object

stored in the stack.stored in the stack. Default constructor: stack::stack() declares Default constructor: stack::stack() declares

an empty stack.an empty stack. Constructor with sequence: stack::stack(c) Constructor with sequence: stack::stack(c)

declares a stack having the same declares a stack having the same elements as container c.elements as container c.

Stack 3Stack 3

Copy constructor, destructor, assignment Copy constructor, destructor, assignment operator, size(), empty()operator, size(), empty()

top() returns a mutable reference to the top() returns a mutable reference to the top of the stack. It actually returns top of the stack. It actually returns c.back().c.back().

push(x) inserts x at the top of the stack. push(x) inserts x at the top of the stack. Calls c.push_back(x).Calls c.push_back(x).

Stack 4Stack 4

pop() removes (but does not return) the pop() removes (but does not return) the element at the top of the stack. Calls element at the top of the stack. Calls c.pop_back().c.pop_back().

Type Requirements: Container C is a Type Requirements: Container C is a model of Back Insertion Sequence.model of Back Insertion Sequence.

QueueQueue

Concept:Concept: A queue adapts a sequence A queue adapts a sequence container (deque by default). A queue is a container (deque by default). A queue is a model of a “first in first out” container. model of a “first in first out” container. Elements are inserted at the back and Elements are inserted at the back and removed from the front of the sequence. removed from the front of the sequence. Iterators are not allowed on queues.Iterators are not allowed on queues.

Template parameters:Template parameters: queue<T,C>. Here T queue<T,C>. Here T is the type of element stored in stack and C is is the type of element stored in stack and C is the underlying sequence container.the underlying sequence container.

Queue 2Queue 2

Members:Members: queue::value_type is the type of object queue::value_type is the type of object

stored in the queue.stored in the queue. Default constructor: queue::queue() Default constructor: queue::queue()

declares an empty queue.declares an empty queue. Constructor with sequence: queue:: Constructor with sequence: queue::

queue(c) declares a queue having the queue(c) declares a queue having the same elements as container c.same elements as container c.

Queue 3Queue 3 Copy constructor, destructor, assignment Copy constructor, destructor, assignment

operator, size(), empty()operator, size(), empty() front() returns the element at the front of front() returns the element at the front of

the queue. Calls c.front().the queue. Calls c.front(). back() returns the element at the back of back() returns the element at the back of

the queue. Calls c.back().the queue. Calls c.back(). push(x) inserts x at the back of the queue. push(x) inserts x at the back of the queue.

No value is returned. Calls No value is returned. Calls c.push_back(x).c.push_back(x).

Queue 4Queue 4

pop() removes the element at the front of pop() removes the element at the front of the queue.the queue.

Type RequirementsType Requirements: Container C is a : Container C is a model for Back Insertion Sequence and model for Back Insertion Sequence and Front Insertion Sequence.Front Insertion Sequence.

Priority QueuePriority Queue

Concept:Concept: A priority queue adapts a A priority queue adapts a sequence container (vector by default). It sequence container (vector by default). It provides for insertion of elements, and provides for insertion of elements, and inspection and removal of the top element. inspection and removal of the top element. Iterators and the modification of elements Iterators and the modification of elements are not permitted. The top element is are not permitted. The top element is always the largest in the queue (elements always the largest in the queue (elements are ordered using < by default). The are ordered using < by default). The elements are stored in a heap.elements are stored in a heap.

Priority Queue 2Priority Queue 2

Template Parameters:Template Parameters: priority_queue<T,C,Compare>. T is the priority_queue<T,C,Compare>. T is the type of element stored in queue. C is the type of element stored in queue. C is the underlying sequence container. Compare underlying sequence container. Compare is the comparison function used to find the is the comparison function used to find the largest element in the queue.largest element in the queue.

Priority Queue 3Priority Queue 3 Members:Members: priority_queue::value_type is the same as priority_queue::value_type is the same as

T.T. Default constructor creates a priority Default constructor creates a priority

queue with the default container and queue with the default container and compare function.compare function.

Constructor with compare function: explicit Constructor with compare function: explicit priority_queue::priority_queue(Compare priority_queue::priority_queue(Compare comp).comp).

Priority Queue 4Priority Queue 4

Constructor with comparison and Constructor with comparison and sequence: sequence: priority_queue::priority_queue(Compare priority_queue::priority_queue(Compare comp, C cont).comp, C cont).

Range constructor with comparison, range Range constructor with comparison, range constructor with comparison and constructor with comparison and container.container.

Priority Queue 5Priority Queue 5

Destructor, assignment operator, size(), Destructor, assignment operator, size(), empty().empty().

top() returns a const reference to the top() returns a const reference to the largest element of the queue (which would largest element of the queue (which would be the root of the heap). Calls c.front().be the root of the heap). Calls c.front().

push(x) inserts x into the queue. Calls push(x) inserts x into the queue. Calls c.push_back() and then “bubbles up” the c.push_back() and then “bubbles up” the heap.heap.

Priority Queue 6Priority Queue 6

pop() removes the element at the top of pop() removes the element at the top of the queue. Switches the top and bottom the queue. Switches the top and bottom elements of the heap, rebuilds the hea, elements of the heap, rebuilds the hea, and then calls c.pop_back().and then calls c.pop_back().

Type Requirements:Type Requirements: Container must be a Container must be a Random Access Container. Compare Random Access Container. Compare must be a Strict Weak Ordering.must be a Strict Weak Ordering.

FunctorsFunctors A functor, or function object, is any object that A functor, or function object, is any object that

can be used using function call syntax.can be used using function call syntax. A function pointer is a functor, as is any object of A function pointer is a functor, as is any object of

a class that overloads the function call operator, a class that overloads the function call operator, i.e., operator().i.e., operator().

A pointer to a member function is not a functor.A pointer to a member function is not a functor. The standard library functors are limited to The standard library functors are limited to

generators, unary and binary functions, but still generators, unary and binary functions, but still provide a useful starting point for someone provide a useful starting point for someone writing their own functors.writing their own functors.

Functors 2Functors 2

A unary function returning a bool is called A unary function returning a bool is called a Predicate. A binary function returning a a Predicate. A binary function returning a bool is called a Binary Predicate.bool is called a Binary Predicate.

An adaptable functor has typedefs for its An adaptable functor has typedefs for its argument types and return type.argument types and return type.

Adaptable functors can be used by Adaptable functors can be used by function adaptors. function adaptors.

GeneratorGenerator

Concept:Concept: A Generator is a function object A Generator is a function object called with no arguments.called with no arguments.

Refines:Refines: Assignable Assignable Associated Types:Associated Types: Result type, the type Result type, the type

returned when the Generator is called.returned when the Generator is called. Operations: fOperations: function call f().unction call f(). Models:Models: any function R (*)(). any function R (*)().

Unary FunctionUnary Function

Concept:Concept: A Unary Function is a function A Unary Function is a function object that is called with a single object that is called with a single argument.argument.

Refines:Refines: Assignable Assignable Associated Types:Associated Types: Argument type: Argument type is the type Argument type: Argument type is the type

of the function’s argument.of the function’s argument.

Unary Function 2Unary Function 2

Result type: result_type is the type of the Result type: result_type is the type of the return value.return value.

Operation:Operation: function call f(x) function call f(x) Models: Models: any function R (*)(T)any function R (*)(T)

Binary FunctionBinary Function

Concept:Concept: A Binary Function is a function A Binary Function is a function object that is called with two arguments.object that is called with two arguments.

Refines:Refines: Assignable Assignable Associated Types:Associated Types: Argument types: First argument type and Argument types: First argument type and

Second argument type are the types of the Second argument type are the types of the function’s arguments.function’s arguments.

Binary Function 2Binary Function 2

Result type: Result type is the type of the Result type: Result type is the type of the return value.return value.

Operation:Operation: function call f(x,y) function call f(x,y) Models: Models: any function R (*)(T1,T2)any function R (*)(T1,T2)

Adaptive GeneratorAdaptive Generator

Concept:Concept: An Adaptive Generator is a An Adaptive Generator is a Generator that has a nested typedef for Generator that has a nested typedef for the return type.the return type.

Refines:Refines: Assignable Assignable Associated Types:Associated Types: f::result_type, the type f::result_type, the type

returned when the Generator is called.returned when the Generator is called. Operations: fOperations: function call f().unction call f(). Models:Models: None in standard library None in standard library

Adaptive Unary FunctionAdaptive Unary Function

Concept:Concept: An Adaptive Unary Function is a An Adaptive Unary Function is a Unary Function that has nested typedefs Unary Function that has nested typedefs for the argument and return types.for the argument and return types.

Refines:Refines: Assignable Assignable Associated Types:Associated Types: Argument type: f::argument_type is the Argument type: f::argument_type is the

type of the function’s argument.type of the function’s argument.

Adaptive Unary Function 2Adaptive Unary Function 2

Result type: f::result_type is the type of the Result type: f::result_type is the type of the return value.return value.

Operation:Operation: function call f(x) function call f(x) Models: Models: negate, logical_not, negate, logical_not,

pointer_to_unary_function.pointer_to_unary_function.

Adaptive Binary FunctionAdaptive Binary Function

Concept:Concept: An Adaptive Binary Function is An Adaptive Binary Function is a Binary Function with nested typedefs for a Binary Function with nested typedefs for the argument and return types.the argument and return types.

Refines:Refines: Assignable Assignable Associated Types:Associated Types: Argument types: f::first_argument_type Argument types: f::first_argument_type

and f::second_argument_type are the and f::second_argument_type are the types of the function’s arguments.types of the function’s arguments.

Adaptive Binary Function 2Adaptive Binary Function 2

Result type: result_type is the type of the Result type: result_type is the type of the return value.return value.

Operation:Operation: function call f(x,y) function call f(x,y) Models: Models: plus, minus, multiplies, divides, plus, minus, multiplies, divides,

modulus, equal_to, not_equal_to, greater, modulus, equal_to, not_equal_to, greater, less, greater_equal, less_equal, less, greater_equal, less_equal, logical_and, logical_or, logical_and, logical_or, pointer_to_binary_function.pointer_to_binary_function.

PredicatePredicate

Concept:Concept: A Predicate is a Unary Function A Predicate is a Unary Function whose return is a bool.whose return is a bool.

Refines:Refines: Unary Function Unary Function Associated Type:Associated Type: the Result type must the Result type must

be convertible to bool.be convertible to bool. Models:Models: Any function of the form Any function of the form

bool (*)(T)bool (*)(T)

Binary PredicateBinary Predicate

Concept:Concept: A Binary Predicate is a Binary A Binary Predicate is a Binary Function that returns a bool.Function that returns a bool.

Refines:Refines: Binary Function Binary Function Associated Types:Associated Types: the Result type must the Result type must

be a bool.be a bool. Models:Models: Any function of the form Any function of the form

bool (*)(T1,T2)bool (*)(T1,T2)

Adaptive PredicateAdaptive Predicate

Concept:Concept: An Adaptive Predicate is a An Adaptive Predicate is a Predicate with nested typedefs for the Predicate with nested typedefs for the argument and return types.argument and return types.

Refines:Refines: Predicate, Adaptive Unary Predicate, Adaptive Unary FunctionFunction

Models: logical_notModels: logical_not

Adaptive Binary PredicateAdaptive Binary Predicate

Concept:Concept: An Adaptive Binary Predicate is An Adaptive Binary Predicate is a Binary Predicate with nested typedefs a Binary Predicate with nested typedefs for the argument and return types.for the argument and return types.

Refines:Refines: Binary Predicate, Adaptive Unary Binary Predicate, Adaptive Unary FunctionFunction

Models:Models: equal_to, not_equal_to, greater, equal_to, not_equal_to, greater, less, greater_equal, less_equal, less, greater_equal, less_equal, logical_and, logical_orlogical_and, logical_or

ExampleExample Here is an example of a user defined adaptive binary Here is an example of a user defined adaptive binary

predicate. This functor returns true if string s1 contains predicate. This functor returns true if string s1 contains string s2 as a substring.string s2 as a substring.

  class str_contains : public class str_contains : public

binary_function<string,string,bool>{binary_function<string,string,bool>{public:public: bool operator() (const string &s1, const string &s2)bool operator() (const string &s1, const string &s2) {{ return s1.find(s2) != string::npos;return s1.find(s2) != string::npos; }}};};

RNG ExampleRNG Example

Here is an adaptive unary functor that was Here is an adaptive unary functor that was almost part of STL.almost part of STL.

This is an example of a subtractive This is an example of a subtractive random number generator.random number generator.

RNG Example 2RNG Example 2class subtractive_rng : public class subtractive_rng : public

std::unary_function<unsigned int, unsigned int> {std::unary_function<unsigned int, unsigned int> {private:private: unsigned int _M_table[55];unsigned int _M_table[55]; size_t _M_index1;size_t _M_index1; size_t _M_index2;size_t _M_index2;public:public: // Returns a number less than the argument.// Returns a number less than the argument. unsigned int operator()(unsigned int __limit) {unsigned int operator()(unsigned int __limit) { _M_index1 = (_M_index1 + 1) % 55;_M_index1 = (_M_index1 + 1) % 55; _M_index2 = (_M_index2 + 1) % 55;_M_index2 = (_M_index2 + 1) % 55; _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index1] = _M_table[_M_index1] -

_M_table[_M_index2];_M_table[_M_index2]; return _M_table[_M_index1] % __limit;return _M_table[_M_index1] % __limit; }}

RNG Example 3RNG Example 3void _M_initialize(unsigned int __seed)void _M_initialize(unsigned int __seed) {{ unsigned int __k = 1;unsigned int __k = 1; _M_table[54] = __seed;_M_table[54] = __seed; size_t __i;size_t __i; for (__i = 0; __i < 54; __i++) {for (__i = 0; __i < 54; __i++) { size_t __ii = (21 * (__i + 1) % 55) - 1;size_t __ii = (21 * (__i + 1) % 55) - 1; _M_table[__ii] = __k;_M_table[__ii] = __k; __k = __seed - __k;__k = __seed - __k; __seed = _M_table[__ii];__seed = _M_table[__ii]; }} for (int __loop = 0; __loop < 4; __loop++) {for (int __loop = 0; __loop < 4; __loop++) { for (__i = 0; __i < 55; __i++)for (__i = 0; __i < 55; __i++) _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55];_M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55]; }} _M_index1 = 0;_M_index1 = 0; _M_index2 = 31;_M_index2 = 31; }}

RNG Example 4RNG Example 4 // Ctor allowing you to initialize the seed.// Ctor allowing you to initialize the seed. subtractive_rng(unsigned int __seed) { _M_initialize(__seed); }subtractive_rng(unsigned int __seed) { _M_initialize(__seed); }

// Default ctor; initializes its state with some number you don't see.// Default ctor; initializes its state with some number you don't see. subtractive_rng() { _M_initialize(161803398u); }subtractive_rng() { _M_initialize(161803398u); } }; }; main()main(){ { subtractive_rng s;subtractive_rng s; for(int i = 0; i < 20; i++)for(int i = 0; i < 20; i++) std::cout << s(10) << ' ';std::cout << s(10) << ' '; std::cout << '\n';std::cout << '\n';} }

RNG Example 5RNG Example 5

Here is the output from the above Here is the output from the above program.program.

3 2 1 6 7 0 7 8 0 9 3 2 1 7 6 9 3 1 0 63 2 1 6 7 0 7 8 0 9 3 2 1 7 6 9 3 1 0 6

Function adaptorsFunction adaptors

A function adaptor converts one type of A function adaptor converts one type of function object into another type.function object into another type.

For example, the functions bind1st and For example, the functions bind1st and bind2nd convert an Adaptable Binary bind2nd convert an Adaptable Binary Function into an Adaptable Unary Function into an Adaptable Unary Function.Function.

Class binder1stClass binder1st Takes an Adaptable Binary Function F(x,y) Takes an Adaptable Binary Function F(x,y)

and converts it into an Adaptable Unary and converts it into an Adaptable Unary Function Function f(y) = F(c,y)f(y) = F(c,y) where c is a where c is a constant.constant.

The function bind1st returns a binder1st The function bind1st returns a binder1st object.object.

For example, bind1st(equal_to<int>(),10) For example, bind1st(equal_to<int>(),10) returns a function object which acts like returns a function object which acts like equal_to(10,y).equal_to(10,y).

Class binder1st 2Class binder1st 2template <class _Operation>template <class _Operation> class binder1stclass binder1st : public unary_function<: public unary_function<

typename typename _Operation::second_argument_type,_Operation::second_argument_type,

typename _Operation::result_type>typename _Operation::result_type>{{protected:protected: _Operation op;_Operation op; typename _Operation::first_argument_type value;typename _Operation::first_argument_type value;

Class binder1st 3Class binder1st 3public:public: binder1st(const _Operation& __x,binder1st(const _Operation& __x, const typename _Operation::first_argument_type& __y)const typename _Operation::first_argument_type& __y) : op(__x), value(__y) { }: op(__x), value(__y) { } typename _Operation::result_type typename _Operation::result_type operator() operator() (const typename (const typename

_Operation::second_argument_type& __x) const_Operation::second_argument_type& __x) const { return op(value, __x); }{ return op(value, __x); }

};};

Class binder1st 4Class binder1st 4template <class _Operation, class _Tp>template <class _Operation, class _Tp> inline binder1st<_Operation>inline binder1st<_Operation> bind1st(const _Operation& __fn, bind1st(const _Operation& __fn, const _Tp& __x)const _Tp& __x){{ typedef typename _Operation::first_argument_type typedef typename _Operation::first_argument_type

_Arg1_type;_Arg1_type;

return binder1st<_Operation>(__fn, _Arg1_type(__x));return binder1st<_Operation>(__fn, _Arg1_type(__x));} }

Class binder2ndClass binder2nd Takes an Adaptable Binary Function F(x,y) Takes an Adaptable Binary Function F(x,y)

and converts it into an Adaptable Unary and converts it into an Adaptable Unary Function Function f(x) = F(x,c)f(x) = F(x,c) where c is a where c is a constant.constant.

The function bind2nd returns a binder2nd The function bind2nd returns a binder2nd object.object.

For example, bind2nd(equal_to<int>(),10) For example, bind2nd(equal_to<int>(),10) returns a function object which acts like returns a function object which acts like equal_to(x,10).equal_to(x,10).

Binder exampleBinder example

We have a list of student grades. We want to We have a list of student grades. We want to copy the grades which are below 60 into a copy the grades which are below 60 into a failures list. Since STL does not provide a failures list. Since STL does not provide a copy_if function we use the next best thing, the copy_if function we use the next best thing, the remove_copy_if function. remove_copy_if function.

This function copies all elements from a source This function copies all elements from a source range for which a given predicate evaluates as range for which a given predicate evaluates as false (i.e., it 'removes' the ones which make false (i.e., it 'removes' the ones which make the predicate true). the predicate true).

Binder example 2Binder example 2

So we will remove_copy_if() all grades So we will remove_copy_if() all grades which are greater than or equal to 60. which are greater than or equal to 60. There is a built-in greater_equal binary There is a built-in greater_equal binary predicate. We will bind its second predicate. We will bind its second argument to 60, to turn it into the unary argument to 60, to turn it into the unary predicate that we want to use.predicate that we want to use.

Binder example 3Binder example 3main()main(){{ int a[10] = { 50, 80, 60, 40, 30, 90, 100, 20 ,40 ,70 };int a[10] = { 50, 80, 60, 40, 30, 90, 100, 20 ,40 ,70 }; vector<int> grades(&a[0], &a[10]);vector<int> grades(&a[0], &a[10]); vector<int> failures;vector<int> failures;   remove_copy_if(grades.begin(), grades.end(),remove_copy_if(grades.begin(), grades.end(),

back_inserter(failures), back_inserter(failures), bind2nd(greater_equal<int>(),60));bind2nd(greater_equal<int>(),60));

   cout << "Failing grades\n";cout << "Failing grades\n"; copy(failures.begin(), failures.end(), ostream<int>(cout, “ "));copy(failures.begin(), failures.end(), ostream<int>(cout, “ "));

return 0;return 0;}}

Binder example 4Binder example 4

OutputOutput

Failing gradesFailing grades50 40 30 20 4050 40 30 20 40

Class pointer_to_unary_functionClass pointer_to_unary_function

Takes a pointer to a unary function and Takes a pointer to a unary function and converts it into an Adaptable Unary converts it into an Adaptable Unary Function.Function.

The function ptr_fun returns a The function ptr_fun returns a pointer_to_unary_function object.pointer_to_unary_function object.

pointer_to_unary_function 2pointer_to_unary_function 2 template <class _Arg, class _Result>template <class _Arg, class _Result> class pointer_to_unary_function : class pointer_to_unary_function :

public unary_function<_Arg, _Result> public unary_function<_Arg, _Result> {{ protected:protected: _Result (*_M_ptr)(_Arg);_Result (*_M_ptr)(_Arg); public:public: pointer_to_unary_function() { }pointer_to_unary_function() { }

pointer_to_unary_function 3pointer_to_unary_function 3

explicit pointer_to_unary_function(_Result explicit pointer_to_unary_function(_Result (*__x)(_Arg)) : _M_ptr(__x) { }(*__x)(_Arg)) : _M_ptr(__x) { } _Result operator() (_Arg __x) const_Result operator() (_Arg __x) const { return _M_ptr(__x); }{ return _M_ptr(__x); } };};

pointer_to_unary_function 4pointer_to_unary_function 4

template <class _Arg, class _Result>template <class _Arg, class _Result> inline pointer_to_unary_function<_Arg, _Result>inline pointer_to_unary_function<_Arg, _Result> ptr_fun(_Result (*__x)(_Arg)) { ptr_fun(_Result (*__x)(_Arg)) {

return return pointer_to_unary_function<_Arg, _Result>(__x); pointer_to_unary_function<_Arg, _Result>(__x);

}}

ExampleExample

Suppose we want to transform the Suppose we want to transform the elements of a vector into the negative of elements of a vector into the negative of their absolute value.their absolute value.

Example 2Example 2

vector<int> v;vector<int> v;//…//…transform(v.begin(), v.end(), v.begin(),transform(v.begin(), v.end(), v.begin(),

compose1(negate<int>(),compose1(negate<int>(), ptr_fun(fabs)));ptr_fun(fabs)));

Example 3Example 3

Here compose1 is a function returning the Here compose1 is a function returning the function adaptor, unary_compose.function adaptor, unary_compose.

The function unary_compose takes two The function unary_compose takes two functions f, g and returns their composition functions f, g and returns their composition h defined by h(x) = f(g(x)).h defined by h(x) = f(g(x)).

These elements, compose1 and These elements, compose1 and unary_compose are not in the C++ unary_compose are not in the C++ standard.standard.

Example 4Example 4

template <class OP1, class OP2>template <class OP1, class OP2>class unary_compose: publicclass unary_compose: public std::unary_function<typename OP2::argument_type, std::unary_function<typename OP2::argument_type,                               typename OP1::result_type>                               typename OP1::result_type>{{  private:  private:    OP1 op1;        OP1 op1;    // process: op1(op2(x))// process: op1(op2(x))    OP2 op2;    OP2 op2;

Example 5Example 5  public:public:

        // constructor// constructor    unary_compose(const OP1& o1, const OP2& o2)    unary_compose(const OP1& o1, const OP2& o2)     : op1(o1), op2(o2) {     : op1(o1), op2(o2) {    }    }

        // function call// function call    typename OP1::result_type    typename OP1::result_type    operator()(const typename OP2::argument_type& x)     operator()(const typename OP2::argument_type& x) 

const const  {      return op1(op2(x));   }{      return op1(op2(x));   }

};};

Example 6Example 6

template <class OP1, class OP2>template <class OP1, class OP2>inline unary_compose<OP1,OP2>inline unary_compose<OP1,OP2>compose1(const OP1& o1, const OP2& o2compose1(const OP1& o1, const OP2& o2

{{    return unary_compose<OP1,OP2>(o1,o2);    return unary_compose<OP1,OP2>(o1,o2);

}}

Class pointer_to_binary_functionClass pointer_to_binary_function

Takes a pointer to a binary function and Takes a pointer to a binary function and converts it into an Adaptable Binary converts it into an Adaptable Binary Function.Function.

The function ptr_fun returns a The function ptr_fun returns a pointer_to_binary_function object.pointer_to_binary_function object.

Class pointer_to_binary_function 2Class pointer_to_binary_function 2

template <class _Arg1, class _Arg2, class template <class _Arg1, class _Arg2, class _Result>_Result>

class pointer_to_binary_functionclass pointer_to_binary_function : public binary_function<_Arg1, _Arg2, _Result>: public binary_function<_Arg1, _Arg2, _Result> {{ protected:protected: _Result (*_M_ptr)(_Arg1, _Arg2);_Result (*_M_ptr)(_Arg1, _Arg2); public:public: pointer_to_binary_function() { }pointer_to_binary_function() { }

Class pointer_to_binary_function 3Class pointer_to_binary_function 3

explicitexplicit pointer_to_binary_function(pointer_to_binary_function(

_Result (*__x)(_Arg1, _Arg2))_Result (*__x)(_Arg1, _Arg2)) : _M_ptr(__x) { }: _M_ptr(__x) { } _Result _Result operator()(_Arg1 __x, _Arg2 __y) constoperator()(_Arg1 __x, _Arg2 __y) const { return _M_ptr(__x, __y); }{ return _M_ptr(__x, __y); }};};

Class pointer_to_binary_function 4Class pointer_to_binary_function 4

template <class _Arg1, class _Arg2, class _Result>template <class _Arg1, class _Arg2, class _Result> inline pointer_to_binary_function<_Arg1, _Arg2, inline pointer_to_binary_function<_Arg1, _Arg2,

_Result>_Result> ptr_fun(_Result (*__x)(_Arg1, _Arg2))ptr_fun(_Result (*__x)(_Arg1, _Arg2)) { {

return return pointer_to_binary_function<_Arg1, _Arg2, pointer_to_binary_function<_Arg1, _Arg2,

_Result>(__x); _Result>(__x); }}

ExampleExample

list<char *> L;list<char *> L;

list<char *>::iterator li =list<char *>::iterator li =find_if(L.begin(), L.end(),find_if(L.begin(), L.end(),

not1(binder2nd(ptr_fun(strcmp), not1(binder2nd(ptr_fun(strcmp), “OK”)));“OK”)));

Class unary_negateClass unary_negate

Class unary_negate is an Adaptable Class unary_negate is an Adaptable Predicate that represents logical negation Predicate that represents logical negation of some other Adaptable Predicate.of some other Adaptable Predicate.

If f is a unary_negate object constructed If f is a unary_negate object constructed with predicate pred, then f(x) returns !with predicate pred, then f(x) returns !pred(x).pred(x).

The function not1 returns a unary_negate The function not1 returns a unary_negate object.object.

Class binary_negateClass binary_negate Class binary_negate is an Adaptable Class binary_negate is an Adaptable

Binary Predicate that represents logical Binary Predicate that represents logical negation of some other Adaptable Binary negation of some other Adaptable Binary Predicate.Predicate.

If f is a binary_negate object constructed If f is a binary_negate object constructed with predicate pred, then f(x,y) returns !with predicate pred, then f(x,y) returns !pred(x,y).pred(x,y).

The function not2 returns a binary_negate The function not2 returns a binary_negate object.object.

ExampleExample

struct U : public binary_function<U,U,bool> {struct U : public binary_function<U,U,bool> {int id;int id;bool operator() (const U &x, const U &y) {bool operator() (const U &x, const U &y) {

return x.id >= y.id;return x.id >= y.id;}}

};};

Example 2Example 2

main() {main() {vector<U> v;vector<U> v;

//Sort v in ascending order.//Sort v in ascending order.sort(v.begin(), v.end(), not2(U()));sort(v.begin(), v.end(), not2(U()));

}}

Class mem_fun_tClass mem_fun_t Class mem_fun_t is a function adaptor Class mem_fun_t is a function adaptor

that takes a member function with that takes a member function with signature R X::f() and makes it possible to signature R X::f() and makes it possible to call it as if it were an ordinary function.call it as if it were an ordinary function.

If F is a mem_fun_t that was constructed If F is a mem_fun_t that was constructed to use X::f and x is an X* pointer then F(x) to use X::f and x is an X* pointer then F(x) is equivalent to x->f().is equivalent to x->f().

The function mem_fun returns a The function mem_fun returns a mem_fun_t object.mem_fun_t object.

Class mem_fun_t 2Class mem_fun_t 2 There are several similar function objects.There are several similar function objects. The class const_mem_fun_t adapts a The class const_mem_fun_t adapts a

member function of the form R X::f() const.member function of the form R X::f() const. The class mem_fun_ref_t has its The class mem_fun_ref_t has its

operator() take an X& argument. So that operator() take an X& argument. So that F(x) is equivalent to x.f(). The F(x) is equivalent to x.f(). The corresponding function is mem_fun_ref().corresponding function is mem_fun_ref().

The class const_mem_fun_ref_t adapts a The class const_mem_fun_ref_t adapts a const member function.const member function.

Class mem_fun_t 3Class mem_fun_t 3template <class _Ret, class _Tp>template <class _Ret, class _Tp> class mem_fun_t : public unary_function<_Tp*, _Ret>class mem_fun_t : public unary_function<_Tp*, _Ret> {{ public:public: explicitexplicit mem_fun_t(_Ret (_Tp::*__pf)())mem_fun_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {}: _M_f(__pf) {}

_Ret operator()(_Tp* __p) const_Ret operator()(_Tp* __p) const { return (__p->*_M_f)(); } { return (__p->*_M_f)(); }

private:private: _Ret (_Tp::*_M_f)();_Ret (_Tp::*_M_f)(); };};

Class mem_fun_t 4Class mem_fun_t 4

template <class _Ret, class _Tp>template <class _Ret, class _Tp> inline mem_fun_t<_Ret, _Tp> inline mem_fun_t<_Ret, _Tp> mem_fun(_Ret (_Tp::*__f)())mem_fun(_Ret (_Tp::*__f)()) { return mem_fun_t<_Ret, _Tp>(__f); }{ return mem_fun_t<_Ret, _Tp>(__f); }

ExampleExamplestruct B {struct B { virtual void print() = 0;virtual void print() = 0;};};

struct C: public B {struct C: public B { void print() { std::cout << "I'm a C\n"; }void print() { std::cout << "I'm a C\n"; }};};

struct D: public B {struct D: public B { void print() { std::cout << "I'm a D\n"; }void print() { std::cout << "I'm a D\n"; }};};

Example 2Example 2main() {main() { std::vector<B*> vbp;std::vector<B*> vbp;

vbp.push_back(new C);vbp.push_back(new C); vbp.push_back(new D);vbp.push_back(new D); vbp.push_back(new C);vbp.push_back(new C); vbp.push_back(new D);vbp.push_back(new D);

std::for_each(vbp.begin(), vbp.end(), std::for_each(vbp.begin(), vbp.end(), std::mem_fun(&B::print));std::mem_fun(&B::print));

Example 3Example 3

std::vector<C> vb;std::vector<C> vb;

vb.push_back(C());vb.push_back(C()); vb.push_back(C());vb.push_back(C());

std::for_each(vb.begin(), vb.end(),std::for_each(vb.begin(), vb.end(),std::mem_fun_ref(&B::print));std::mem_fun_ref(&B::print));

Example 4Example 4 std::vector<std::vector<int> > vi;std::vector<std::vector<int> > vi;

vi.push_back(std::vector<int>(2));vi.push_back(std::vector<int>(2)); vi.push_back(std::vector<int>(7));vi.push_back(std::vector<int>(7)); vi.push_back(std::vector<int>(6));vi.push_back(std::vector<int>(6)); transform(vi.begin(),vi.end(),transform(vi.begin(),vi.end(), std::ostream_iterator<int>(std::cout, " "),std::ostream_iterator<int>(std::cout, " "), std::mem_fun_ref(&std::vector<int>::size));std::mem_fun_ref(&std::vector<int>::size)); std::cout << '\n'; std::cout << '\n';

Example 5Example 5 OutputOutputI'm a CI'm a CI'm a DI'm a DI'm a CI'm a CI'm a DI'm a DI'm a CI'm a CI'm a CI'm a C2 7 6 2 7 6

Class mem_fun1_tClass mem_fun1_t Class mem_fun1_t is a function adaptor that Class mem_fun1_t is a function adaptor that

takes a member function with signature R X::f(A) takes a member function with signature R X::f(A) and makes it possible to call it as if it were an and makes it possible to call it as if it were an ordinary function.ordinary function.

If F is a mem_fun1_t that was constructed to use If F is a mem_fun1_t that was constructed to use X::f, a is a value of type A and x is an X* pointer X::f, a is a value of type A and x is an X* pointer then F(x) is equivalent to x->f(a).then F(x) is equivalent to x->f(a).

The function mem_fun returns a mem_fun1_t The function mem_fun returns a mem_fun1_t object.object.

Class mem_fun1_t 2Class mem_fun1_t 2

There are also function objects There are also function objects mem_fun1_ref_t, const_mem_fun1_t, and mem_fun1_ref_t, const_mem_fun1_t, and const_mem_fun1_ref_t.const_mem_fun1_ref_t.

STL AlgorithmsSTL Algorithmsfor_each()for_each()  Function Function for_eachfor_each(InputIterator beg, InputIterator end, Function f)(InputIterator beg, InputIterator end, Function f) - Applies function f to each element in range [beg,end)- Applies function f to each element in range [beg,end) - Returns f- Returns f    Nonmutating AlgorithmsNonmutating Algorithms  size_t size_t countcount(InputIterator beg, InputIterator end, const T &val)(InputIterator beg, InputIterator end, const T &val) - Returns the number of occurrences of val in range [beg,end)- Returns the number of occurrences of val in range [beg,end)size_t size_t countcount(InputIterator beg, InputIterator end, const T &val, Size &n)(InputIterator beg, InputIterator end, const T &val, Size &n) - Adds the number of occurrences of val in [beg,end) to n- Adds the number of occurrences of val in [beg,end) to n

STL Algorithms 2STL Algorithms 2

size_t count_if(InputIterator beg, InputIterator end, Predicate pred)size_t count_if(InputIterator beg, InputIterator end, Predicate pred) - Returns the number of elements in range [beg,end) for which - Returns the number of elements in range [beg,end) for which

pred is truepred is true    InputIterator min_element(InputIterator beg, InputIterator end)InputIterator min_element(InputIterator beg, InputIterator end)InputIterator max_element(InputIterator beg, InputIterator end)InputIterator max_element(InputIterator beg, InputIterator end) - Returns the minimum or maximum element in range - Returns the minimum or maximum element in range

[beg,end)[beg,end)

STL Algorithms 3STL Algorithms 3bool lexicographical_compare(InputIterator1 beg1, bool lexicographical_compare(InputIterator1 beg1,

InputIterator1 end1,InputIterator1 end1, InputIterator2 beg2, InputIterator end2) (Bin. Pred.)InputIterator2 beg2, InputIterator end2) (Bin. Pred.) - Returns whether or not the elements in the range - Returns whether or not the elements in the range

[beg1,end1) are less than the elements in the range [beg2,end2)[beg1,end1) are less than the elements in the range [beg2,end2)    Search FunctionsSearch Functions    InputIterator find(InputIterator beg, InputIterator end, const T &val)InputIterator find(InputIterator beg, InputIterator end, const T &val) - Finds and returns the first position of val in range [beg,end)- Finds and returns the first position of val in range [beg,end) - Returns end if val not found- Returns end if val not found

STL Algorithms 4STL Algorithms 4InputIterator adjacent_find(InputIterator beg, InputIterator adjacent_find(InputIterator beg,

InputIterator end) (Bin. Pred.)InputIterator end) (Bin. Pred.) - Finds and returns the first position in range - Finds and returns the first position in range

[beg,end) for which two consecutive elements are [beg,end) for which two consecutive elements are equalequal

- Returns end if no match found- Returns end if no match found  InputIterator find_if(InputIterator beg, InputIterator end, InputIterator find_if(InputIterator beg, InputIterator end,

Predicate pred)Predicate pred) - Finds and returns the first position in range - Finds and returns the first position in range

[beg,end) for which pred is true[beg,end) for which pred is true - Returns end if no matching element found- Returns end if no matching element found

STL Algorithms 5STL Algorithms 5InputIterator InputIterator adjacent_find_ifadjacent_find_if(InputIterator beg, (InputIterator beg,

InputIterator end, Predicate pred)InputIterator end, Predicate pred) - Finds and returns the first position in range [beg,end) - Finds and returns the first position in range [beg,end)

for which pred is true for two consecutive elementsfor which pred is true for two consecutive elements - Returns end if no match found- Returns end if no match found    InputIterator InputIterator search_nsearch_n(InputIterator beg, InputIterator end, (InputIterator beg, InputIterator end,

Size n, const T &val) (Bin Pred)Size n, const T &val) (Bin Pred) - Finds and returns the first position in range [beg,end) - Finds and returns the first position in range [beg,end)

for which n consecutive vals occur, in the first casefor which n consecutive vals occur, in the first case - Returns end if no matching element found- Returns end if no matching element found

STL Algorithms 6STL Algorithms 6ForwardIterator1 ForwardIterator1 searchsearch(ForwardIterator1 beg1, ForwardIterator1 (ForwardIterator1 beg1, ForwardIterator1

end1, ForwardIterator2 beg2, ForwardIterator2 end2) (Bin Pred)end1, ForwardIterator2 beg2, ForwardIterator2 end2) (Bin Pred) - Returns the position of the first element of the first subrange in - Returns the position of the first element of the first subrange in

the range [beg1,end1) that matches all of the elements in the range the range [beg1,end1) that matches all of the elements in the range [beg2,end2)[beg2,end2)

- Returns end1 if no match found- Returns end1 if no match found    ForwardIterator1 ForwardIterator1 find_endfind_end(ForwardIterator1 beg1, ForwardIterator1 (ForwardIterator1 beg1, ForwardIterator1

end1, ForwardIterator2 beg2, ForwardIterator2 end2) (Bin Pred)end1, ForwardIterator2 beg2, ForwardIterator2 end2) (Bin Pred) - Returns the position of the first element of the last subrange in - Returns the position of the first element of the last subrange in

the range [beg1,end1) that matches all of the elements in the range the range [beg1,end1) that matches all of the elements in the range [beg2,end2)[beg2,end2)

- Returns end1 if no match found- Returns end1 if no match found

STL Algorithms 7STL Algorithms 7ForwardIterator1 ForwardIterator1 find_first_offind_first_of(ForwardIterator1 beg1, (ForwardIterator1 beg1,

ForwardIterator1 end1, ForwardIterator2 beg2, ForwardIterator1 end1, ForwardIterator2 beg2, ForwardIterator2 end2) (Binary Pred)ForwardIterator2 end2) (Binary Pred)

- Returns the postion of the first element in the range - Returns the postion of the first element in the range [beg1,end1) that is also in the range [beg2,end2)[beg1,end1) that is also in the range [beg2,end2)

- Returns end1 if no match found- Returns end1 if no match found    bool bool equalequal(InputIterator1 beg1, InputIterator1 end1, (InputIterator1 beg1, InputIterator1 end1,

InputIterator2 beg2) (Binary Pred)InputIterator2 beg2) (Binary Pred) - Returns whether or not the elements in the range - Returns whether or not the elements in the range

[beg1,end1) are equal to the corresponding elements in [beg1,end1) are equal to the corresponding elements in the range [beg2,end2)the range [beg2,end2)

STL Algorithms 8STL Algorithms 8pair<InputIterator1, InputIterator2> pair<InputIterator1, InputIterator2> mismatchmismatch(InputIterator1 (InputIterator1

beg1, InputIterator1 end1, beg1, InputIterator1 end1, InputIterator2 beg2) (Binary Pred)InputIterator2 beg2) (Binary Pred)

- Returns the first positions in the ranges starting with - Returns the first positions in the ranges starting with beg1 and beg2 that are differentbeg1 and beg2 that are different

- Returns end1 if no mismatch found- Returns end1 if no mismatch found    Mutating AlgorithmsMutating Algorithms  Note: Associative containers cannot be used as the Note: Associative containers cannot be used as the

destination of any of the following algorithms (because of destination of any of the following algorithms (because of the underlying sort of these containers) the underlying sort of these containers)

STL Algorithms 8STL Algorithms 8OutputIterator OutputIterator copycopy(InputIterator sourceBeg, (InputIterator sourceBeg,

InputIterator sourceEnd, OutputIterator destBeg)InputIterator sourceEnd, OutputIterator destBeg) - Copies the range [sourceBeg,sourceEnd) to - Copies the range [sourceBeg,sourceEnd) to

the range starting at position destBeg, the range starting at position destBeg, overwriting the elements already there (no overwriting the elements already there (no memory is allocated, unless insert iterators are memory is allocated, unless insert iterators are used)used)

- The source and destination may overlap- The source and destination may overlap - Returns the position in the destination after - Returns the position in the destination after

the last element copiedthe last element copied

STL Algorithms 9STL Algorithms 9BidirectionalIterator BidirectionalIterator copy_backwardcopy_backward(InputIterator (InputIterator

sourceBeg, InputIterator sourceEnd, sourceBeg, InputIterator sourceEnd, BidirectionalIterator destEnd)BidirectionalIterator destEnd)

- Copies the range [sourceBeg,sourceEnd) to - Copies the range [sourceBeg,sourceEnd) to the range starting at position destEnd (moving the range starting at position destEnd (moving backwards through the destination, so that the backwards through the destination, so that the elements end up in the same order as the elements end up in the same order as the source). Elements are overwritten (no memory is source). Elements are overwritten (no memory is allocated, unless insert iterators are used)allocated, unless insert iterators are used)

- The source and destination may overlap- The source and destination may overlap - Returns the position in destination before the - Returns the position in destination before the

last element copiedlast element copied

STL Algorithms 10STL Algorithms 10OutputIterator OutputIterator transformtransform(InputIterator sourceBeg, (InputIterator sourceBeg,

InputIterator sourceEnd,InputIterator sourceEnd, OutputIterator destBeg, Function f)OutputIterator destBeg, Function f) - Applies the function f to each element of source - Applies the function f to each element of source

range and copies the return value of the function to the range and copies the return value of the function to the destination (no memory is allocated, unless insert destination (no memory is allocated, unless insert iterators are used)iterators are used)

- The source and destination ranges may be the same- The source and destination ranges may be the same - Returns the position after the last element copied- Returns the position after the last element copied

STL Algorithms 11STL Algorithms 11OutputIterator OutputIterator transformtransform(InputIterator1 source1Beg, (InputIterator1 source1Beg,

InputIterator1 source1End,InputIterator1 source1End, InputIterator2 source2Beg, OutputIterator destBeg, InputIterator2 source2Beg, OutputIterator destBeg,

BinaryFunction f)BinaryFunction f) - Applies the binary function f to the corresponding - Applies the binary function f to the corresponding

elements of the two source ranges and copies the return elements of the two source ranges and copies the return value to the destination (no memory is allocated, unless value to the destination (no memory is allocated, unless insert iterators are used)insert iterators are used)

- The source and destination ranges may be the same- The source and destination ranges may be the same - Returns the position after the last element copied- Returns the position after the last element copied

STL Algorithms 12STL Algorithms 12ForwardIterator2 ForwardIterator2 swap_rangesswap_ranges(ForwardIterator1 beg1, (ForwardIterator1 beg1,

ForwardIterator1 end1, ForwardIterator2 beg2)ForwardIterator1 end1, ForwardIterator2 beg2) - Swaps the elements in the ranges beginning with - Swaps the elements in the ranges beginning with

beg1 and beg2beg1 and beg2 - Returns the position after the last swapped element - Returns the position after the last swapped element

in second rangein second range    void void fillfill(ForwardIterator beg, ForwardIterator end, const T (ForwardIterator beg, ForwardIterator end, const T

&val)&val) - Assigns val to the elements in the range [beg,end)- Assigns val to the elements in the range [beg,end)

STL Algorithms 13STL Algorithms 13void void fill_nfill_n(OutputIterator pos, Size n, const T &val)(OutputIterator pos, Size n, const T &val) - Assigns val to the first n elements beginning at - Assigns val to the first n elements beginning at

position posposition pos - Destination must be large enough (else insert - Destination must be large enough (else insert

iterators must be used)iterators must be used)    void void generategenerate(ForwardIterator beg, ForwardIterator end, (ForwardIterator beg, ForwardIterator end,

Function f)Function f) - Assigns the output of function f to the elements in - Assigns the output of function f to the elements in

range [beg,end)range [beg,end) - Note: the elements are not used as input to f (as in - Note: the elements are not used as input to f (as in

the transform algorithm)the transform algorithm)

STL Algorithms 14STL Algorithms 14

void void generate_ngenerate_n(OutputIterator pos, Size n, (OutputIterator pos, Size n, Function f)Function f)

- Assigns the output of f to the n elements - Assigns the output of f to the n elements beginning at position posbeginning at position pos

    void void replacereplace(ForwardIterator beg, ForwardIterator (ForwardIterator beg, ForwardIterator

end, const T &old_val, const T &new_val)end, const T &old_val, const T &new_val) - Replaces each instance of old_val with - Replaces each instance of old_val with

new_val in the range [beg,end)new_val in the range [beg,end)

STL Algorithms 15STL Algorithms 15void void replace_ifreplace_if(ForwardIterator beg, ForwardIterator end, (ForwardIterator beg, ForwardIterator end,

Predicate pred, const T &new_val)Predicate pred, const T &new_val) - Replaces each element in the range [beg,end) which - Replaces each element in the range [beg,end) which

makes pred true with new_valmakes pred true with new_val    void void replace_copyreplace_copy(ForwardIterator beg, ForwardIterator (ForwardIterator beg, ForwardIterator

end, OutputIterator destBeg, const T &old_val, const T end, OutputIterator destBeg, const T &old_val, const T &new_val)&new_val)

- Copies source range to destination range, in the - Copies source range to destination range, in the process it replaces each instance of old_val with process it replaces each instance of old_val with new_val in the destination rangenew_val in the destination range

STL Algorithms 16STL Algorithms 16void void replace_copy_ifreplace_copy_if(ForwardIterator beg, ForwardIterator end, (ForwardIterator beg, ForwardIterator end,

OutputIterator destBeg, Predicate pred, const T &new_val)OutputIterator destBeg, Predicate pred, const T &new_val) - Copies source range to destination range, in the process it - Copies source range to destination range, in the process it

replaces each element that makes pred true with new_val in the replaces each element that makes pred true with new_val in the destination rangedestination range

    Removing AlgorithmsRemoving Algorithms

ForwardIterator ForwardIterator removeremove(ForwardIterator beg, ForwardIterator end, const (ForwardIterator beg, ForwardIterator end, const T &val)T &val)

- "Removes" all elements in the range equal to val- "Removes" all elements in the range equal to val - The "removed" elements are moved to positions after return - The "removed" elements are moved to positions after return

position.position. - The function returns the position after the last element not removed- The function returns the position after the last element not removed

next_permutationnext_permutation#include <iostream>#include <iostream>#include <iterator>#include <iterator>#include <algorithm>#include <algorithm>

template <class BidirectionalIterator>template <class BidirectionalIterator>int snail_sort(BidirectionalIterator first, int snail_sort(BidirectionalIterator first,

BidirectionalIterator last)BidirectionalIterator last){{ int count = 0;int count = 0; while (std::next_permutation(first, last)) { ++count; }while (std::next_permutation(first, last)) { ++count; } return ++count;return ++count;}}

next_permutation 2next_permutation 2int main()int main(){{ int A[] = {7, 1, 3, 8, 4};int A[] = {7, 1, 3, 8, 4}; const int N = sizeof(A) / sizeof(int);const int N = sizeof(A) / sizeof(int); int count = snail_sort(A, A+N);int count = snail_sort(A, A+N); std::cout << "Sort took " << count << " permutations.\n";std::cout << "Sort took " << count << " permutations.\n"; std::copy(A, A+N, std::copy(A, A+N, std::ostream_iterator<int>(std::cout, " "));std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n';std::cout << '\n';

return 0;return 0;}}

next_permutation 3next_permutation 3

Output:Output:

Sort took 47 permutations.Sort took 47 permutations.1 3 4 7 81 3 4 7 8

next_permutation 4next_permutation 4

If we defineIf we define int A[] = {1, 3, 4, 7, 8};int A[] = {1, 3, 4, 7, 8};

Output:Output:

Sort took 120 permutations.Sort took 120 permutations.1 3 4 7 8 1 3 4 7 8

next_permutation 5next_permutation 5

If we defineIf we defineint A[] = {1, 4, 4, 7, 8};int A[] = {1, 4, 4, 7, 8};

Output:Output:

Sort took 60 permutations.Sort took 60 permutations.1 4 4 7 81 4 4 7 8

next_permutation 6next_permutation 6int main()int main(){{ int A[] = {1, 4, 7, 8};int A[] = {1, 4, 7, 8}; const int N = sizeof(A) / sizeof(int);const int N = sizeof(A) / sizeof(int);

int count = 0;int count = 0; while (std::next_permutation(A, A+N)) {while (std::next_permutation(A, A+N)) { ++count;++count; std::copy(A, A+N, std::ostream_iterator<int>(std::cout, " "));std::copy(A, A+N, std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n';std::cout << '\n'; }} ++count;++count; std::cout << "Sort took " << count << " permutations.\n";std::cout << "Sort took " << count << " permutations.\n"; return 0;return 0;}}

next_permutation 7next_permutation 71 4 8 7 1 4 8 7 1 7 4 8 1 7 4 8 1 7 8 4 1 7 8 4 1 8 4 7 1 8 4 7 1 8 7 4 1 8 7 4 4 1 7 8 4 1 7 8 4 1 8 7 4 1 8 7 4 7 1 8 4 7 1 8 4 7 8 1 4 7 8 1 4 8 1 7 4 8 1 7 4 8 7 1 4 8 7 1 7 1 4 8 7 1 4 8 7 1 8 4 7 1 8 4

next_permutation 8next_permutation 87 4 1 8 7 4 1 8 7 4 8 1 7 4 8 1 7 8 1 4 7 8 1 4 7 8 4 1 7 8 4 1 8 1 4 7 8 1 4 7 8 1 7 4 8 1 7 4 8 4 1 7 8 4 1 7 8 4 7 1 8 4 7 1 8 7 1 4 8 7 1 4 8 7 4 1 8 7 4 1 Sort took 24 permutations.Sort took 24 permutations.

next_permutation 9next_permutation 9

template<typename _BidirectionalIterator>template<typename _BidirectionalIterator>bool next_permutation(bool next_permutation( _BidirectionalIterator __first,_BidirectionalIterator __first, _BidirectionalIterator __last)_BidirectionalIterator __last){{ if (__first == __last)if (__first == __last) return false;return false; _BidirectionalIterator __i = __first;_BidirectionalIterator __i = __first; ++__i;++__i;

next_permutation 10next_permutation 10 if (__i == __last)if (__i == __last) return false;return false; __i = __last;__i = __last; --__i;--__i; for( ; ; )for( ; ; ) {{ _BidirectionalIterator __ii = __i;_BidirectionalIterator __ii = __i; --__i;--__i;

next_permutation 11next_permutation 11

if (*__i < *__ii)if (*__i < *__ii) {{ _BidirectionalIterator __j = __last;_BidirectionalIterator __j = __last; while (!(*__i < *--__j)) { }while (!(*__i < *--__j)) { } std::iter_swap(__i, __j);std::iter_swap(__i, __j); std::reverse(__ii, __last);std::reverse(__ii, __last); return true;return true; } }

next_permutation 12next_permutation 12

if (__i == __first)if (__i == __first) {{ std::reverse(__first, __last);std::reverse(__first, __last); return false;return false; }} }} }}

top related