csce-622: generic programming slides 3 [1ex] c++ standard … · 2013-02-18 · polymorphism...
TRANSCRIPT
CSCE-622: Generic Programming— Slides 3
C++ Standard Library (or the STL part of it)
Jaakko Järvi
September 19, 2010
1 / 155
Introduction & History
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
2 / 155
Introduction & History
Standard Template Library in a nutshell
A general-purpose library of generic algorithms and data structurescommunicating through iterators.Contains many small components that can be plugged together andused in applicationsFunctionality and performance requirements are carefully chosen sothat there are a myriad of useful combinations
3 / 155
Introduction & History
Standard Template Library: History
Most notable example of generic programmingWidely used in practiceEarly work on LISP, Ada ⇒ C++Alex Stepanov, David Musser; Stepanov, Meng Lee
Standard Template LibraryProposed to the ANSI/ISO C++ Standards Committee in 1994.After small revisions, part of the official C++ standard in 1997.
4 / 155
Introduction & History
Example: using STL
#include <algorithm>#include <iterator>#include <vector>#include <iostream>
int main() {std::vector<int> vi;std::istream_iterator<int> init(std::cin), end;
std::copy(init, end, std::back_inserter(vi));std::sort(vi.begin(), vi.end());std::unique_copy(
vi.begin(), vi.end(),std::ostream_iterator<int>(std::cout, " "));
}
5 / 155
Introduction & History
Running the example
$ echo ’10 0 42 10’ | sort_int_input.exe
0 10 42
6 / 155
Introduction & History
Connecting containers and algorithms with iteratorsConnecting Containers and Algorithms with Iterators
T
T
T
Container GenericAlgorithmsClasses
vector
list
istreamiteratoristream_
T
ostreamostream_iterator
eraseinsert
eraseinsert
merge
find
sort
Iterators
++
=
*
Increment
Dereference
==, &
Assign --
+, -, < Random Access
Decrement
Compare, Reference
7 / 155
Introduction & History
Five of the six major STL componentsFive of the Six Major STL Component Categories (Concepts)
T
TC
T
Cpop_front
T
T
T
Container GenericAlgorithmsClasses Objects
Function Adaptors
vector
list
istream iteratoristream_ T
ostream ostream_iterator
eraseinsert
eraseinsert
merge
find
sort
equal
less
greater
stack
top
pop
push
queue push_back
Iterators
iterator
reverse
++=
*
Increment
Dereference
==, &Assign --
+, -, < Random AccessDecrementCompare, Reference
GenericParameter
8 / 155
Polymorphism
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
9 / 155
Polymorphism
Aside: About polymorphism
Categorization by Cardelli and Wegner:1
UniversalParametricInclusion
Ad-hocOverloadingCoercion
1"On Understanding Types, Data Abstraction, and Polymorphism", ComputingSurveys 1985http://research.microsoft.com/Users/luca/Papers/OnUnderstanding.pdf
10 / 155
Polymorphism
Aside: About polymorphism
Categorization by Cardelli and Wegner:1
Universal — Same definition works for many typesParametric — type parametrizationInclusion — subtype polymorphism
Ad-hoc — Same function name works, possible differently, for manytypes
Overloading — Same function name defined differently for many typesCoercion — A monomorphic function works for many types, becauseseveral types can be converted to its parameter types
1"On Understanding Types, Data Abstraction, and Polymorphism", ComputingSurveys 1985http://research.microsoft.com/Users/luca/Papers/OnUnderstanding.pdf
10 / 155
Polymorphism
Inclusion polymorphism and parametric polymorphism inC++
Two main approaches to polymorphism in programming:
Inclusion or subtype polymorphismSame function works for all subtypes of a given typeParametric polymorphismRealized with templates that specify a class or a function parametrizedon types.
C++ supports bothClass inheritance ⇒ subtype polymorphismTemplates ⇒ parametric polymorphism
STL uses only parametric polymorphism — generic programming,however, is not limited to parametric polymorphism.Note, STL also relies on ad-hoc polymorphism to select the mostefficient implementations of a given algorithm
11 / 155
Generic programming process → STL
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
12 / 155
Generic programming process → STL
Generic Programming Process
Identify useful and efficient algorithmsFind their generic representation
Categorize functionality of some of these algorithmsWhat do they need to have in order to work in principle
Derive a set of (minimal) requirements that allow these algorithms torun (efficiently)
Now categorize these algorithms and their requirementsAre there overlaps, similarities?
Construct a framework based on classifications and requirementsNow realize this as a software library
Let’s look at that process for developing a library for fundamentalalgorithms necessary for all kinds of programming
Algorithms for basic computer science
13 / 155
Generic programming process → STL
Process“Identify useful and efficient algorithms”Brainstorm: What are some useful and efficient algorithms for CS?
14 / 155
Generic programming process → STL
Standard Library Algorithms
The standard library categorizes its algorithms this way:Non-mutatingMutatingSortingGeneralized numeric
15 / 155
Generic programming process → STL
Non-mutating
find, find_ifadjacent_find
Two of the same values next to each otherfind_first_of
Find any of a set of values
count, count_ifmismatch
Where do two sequences differ
equal
search, find_endsearch for subsequence
search_nsearch for n consecutive elements equal to some value
for_each
16 / 155
Generic programming process → STL
Mutating
copy, copy_n, copy_backwardswap, iter_swap, swap_rangestransform
replace, replace_if, replace_copy, replace_copy_iffill, fill_n, generate, generate_nunique, unique_copy
Remove consecutive duplicates
reverse, reverse_copyrotate, rotate_copyrandom_shuffle, random_shuffle, random_sample, random_sample_n,partition, stable_partition
17 / 155
Generic programming process → STL
Sorting
sort, stable_sort, partial_sort, partial_sort_copy, is_sortednth_element
lower_bound, upper_bound, equal_range, binary_searchmerge, inplace_mergeincludes, set_union, set_intersection, set_difference,set_symmetric_difference
push_heap, pop_heap, make_heap, sort_heap, is_heapmin, max, min_element, max_elementlexicographical_compare
next_permutation, prev_permutation
18 / 155
Generic programming process → STL
Generalized Numeric
accumulate
inner_product
partial_sum
adjacent_difference
19 / 155
Generic programming process → STL
Process“Identify useful and efficient algorithms”
Brainstorm: What do they need to have in order to work in principle?
20 / 155
Generic programming process → STL
for_each
Apply a function to each element in a sequenceRequirements?
21 / 155
Generic programming process → STL
copy
Copy elements from one sequence to anotherRequirements?
22 / 155
Generic programming process → STL
transform
Apply a function to each element of a sequence and put the results inanother sequenceRequirements?
23 / 155
Generic programming process → STL
fill
Assign a value to every element of a sequenceRequirements?
24 / 155
Generic programming process → STL
reverse
Reverse a rangeRequirements?
25 / 155
Generic programming process → STL
sort
Sorts elements of a sequence in ascending orderRequirements?
26 / 155
Generic programming process → STL
find
Find an element in a sequenceRequirements?
27 / 155
Generic programming process → STL
binary_search
Find an element in a sequenceRequirements?
28 / 155
Generic programming process → STL
Process
“Find the generic representation of algorithms”
29 / 155
Generic programming process → STL
Generic representation
One approach
template <class Container, class UnaryFunction>UnaryFunction for_each(Container c, UnaryFunction f);
30 / 155
Generic programming process → STL
Generic representation
Another approach
template <class InputIterator, class UnaryFunction>UnaryFunctionfor_each(InputIterator first, InputIterator last,
UnaryFunction f);
31 / 155
Generic programming process → STL
ProcessDerive a set of (minimal) requirements that allow these algorithms torun (efficiently)
Now categorize these algorithms and their requirementsAre there overlaps, similarities?
32 / 155
Generic programming process → STL
Categorizing requirements
Some algorithms just need to be able to get elements out
Input Iterator
Some algorithms just need to be able to put elements in
Output Iterator
Some algorithms need persistent elements
Forward Iterator
Some algorithms need to be able to “go back”
Bidirectional Iterator
Some algorithms need to be able to arbitrarily access elements (inconstant time)
Random Access Iterator
33 / 155
Generic programming process → STL
Categorizing requirements
Some algorithms just need to be able to get elements outInput Iterator
Some algorithms just need to be able to put elements in
Output Iterator
Some algorithms need persistent elements
Forward Iterator
Some algorithms need to be able to “go back”
Bidirectional Iterator
Some algorithms need to be able to arbitrarily access elements (inconstant time)
Random Access Iterator
33 / 155
Generic programming process → STL
Categorizing requirements
Some algorithms just need to be able to get elements outInput Iterator
Some algorithms just need to be able to put elements inOutput Iterator
Some algorithms need persistent elements
Forward Iterator
Some algorithms need to be able to “go back”
Bidirectional Iterator
Some algorithms need to be able to arbitrarily access elements (inconstant time)
Random Access Iterator
33 / 155
Generic programming process → STL
Categorizing requirements
Some algorithms just need to be able to get elements outInput Iterator
Some algorithms just need to be able to put elements inOutput Iterator
Some algorithms need persistent elementsForward Iterator
Some algorithms need to be able to “go back”
Bidirectional Iterator
Some algorithms need to be able to arbitrarily access elements (inconstant time)
Random Access Iterator
33 / 155
Generic programming process → STL
Categorizing requirements
Some algorithms just need to be able to get elements outInput Iterator
Some algorithms just need to be able to put elements inOutput Iterator
Some algorithms need persistent elementsForward Iterator
Some algorithms need to be able to “go back”Bidirectional Iterator
Some algorithms need to be able to arbitrarily access elements (inconstant time)
Random Access Iterator
33 / 155
Generic programming process → STL
Categorizing requirements
Some algorithms just need to be able to get elements outInput Iterator
Some algorithms just need to be able to put elements inOutput Iterator
Some algorithms need persistent elementsForward Iterator
Some algorithms need to be able to “go back”Bidirectional Iterator
Some algorithms need to be able to arbitrarily access elements (inconstant time)
Random Access Iterator
33 / 155
Generic programming process → STL
Process“Construct a framework based on classifications and requirements”
Our tool is abstractionRealized in STL as concepts
34 / 155
Generic programming process → STL
Framework
Realize these as abstractions somehow and build around them
Input IteratorOutput IteratorForward IteratorBidirectional IteratorRandom Access Iterator
Note: iterator abstractions are just one part of the framework, butwe’ll leave the other parts aside for now.
35 / 155
Concepts
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
36 / 155
Concepts
Concepts
Concepts are the means to describe the requirements on abstractionsNote that “concept” is a technical term in generic programmingIdeally, concepts capture commonly occurring abstractions, they arenot arbitrary collections of requirementsConcepts force many data structures into a common form, enablinggeneric algorithmsConcepts emerge from careful study of (and experiences with)algorithms and data-structures in a particular domain.
37 / 155
Concepts
Concepts
Definition (Concept)
A set R of requirements together with a set A of abstractions, such that anabstraction is included in A if and only if it satisfies all of the requirementsin R .
Requirements Abstractions
Requirement 1
Requirement 2
...
Requirement N
Concept
Abstraction 1
Abstraction 2
...
...
Abstraction K
...
38 / 155
Concepts
Concepts: example
Definition (Concept)
A set R of requirements together with a set A of abstractions, such that anabstraction is included in A if and only if it satisfies all of the requirementsin R .
Requirements Abstractions
Closed plane figure
N sides
. . .
Polygon Concept39 / 155
Concepts
Concepts in software
Definition (Concept)
A set R of requirements together with a set A of abstractions, such that anabstraction is included in A if and only if it satisfies all of the requirementsin R .
Think of A as a set of typesThink of R as a set of operations that the types must support (andother properties that the types must have)Example: Assume a concept 〈R,A〉: if R = {supports ++, supports *},then int* ∈ A.A type that satisfies the requirements of a concept is said to be amodel of that conceptExample: int* is a model of Input Iterator
40 / 155
Concepts
Example
Requirements Models
Must be a type whose objects can store other objects (elements)
Must have an associated iterator type that can be used to iterate through the elements ...
Container Concept
vector<T>, for any Tdeque<T>, for any Tlist<T>, for any Tset<T>, for any Tmap<T>, for any Tself_adjusting_bag ...
Note that we are intentionally very loose in how the requirements aredescribed here
41 / 155
Concept refinement
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
42 / 155
Concept refinement
Iterator Concepts
Input IteratorX p(q), p=q, p==q, p!=q, ++p, p++, *p, p->m, *p++
Output IteratorX p(q), p=q, ++p, p++, *p=expr ., *p++=expr .,
Forward IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref .
Bidirectional IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref .
Random Access IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref . p<q, p<=q, p>q, p>=q, p+n,p-n, p-q, p+=n, p-=n, p[n]
43 / 155
Concept refinement
Iterator Concepts
Input IteratorX p(q), p=q, p==q, p!=q, ++p, p++, *p, p->m, *p++
Output IteratorX p(q), p=q, ++p, p++, *p=expr ., *p++=expr .,
Forward IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref .
Bidirectional IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref .
Random Access IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref . p<q, p<=q, p>q, p>=q, p+n,p-n, p-q, p+=n, p-=n, p[n]
43 / 155
Concept refinement
Iterator Concepts
Input IteratorX p(q), p=q, p==q, p!=q, ++p, p++, *p, p->m, *p++
Output IteratorX p(q), p=q, ++p, p++, *p=expr ., *p++=expr .,
Forward IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref .
Bidirectional IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref .
Random Access IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref . p<q, p<=q, p>q, p>=q, p+n,p-n, p-q, p+=n, p-=n, p[n]
43 / 155
Concept refinement
Iterator Concepts
Input IteratorX p(q), p=q, p==q, p!=q, ++p, p++, *p, p->m, *p++
Output IteratorX p(q), p=q, ++p, p++, *p=expr ., *p++=expr .,
Forward IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref .
Bidirectional IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref .
Random Access IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref . p<q, p<=q, p>q, p>=q, p+n,p-n, p-q, p+=n, p-=n, p[n]
43 / 155
Concept refinement
Iterator Concepts
Input IteratorX p(q), p=q, p==q, p!=q, ++p, p++, *p, p->m, *p++
Output IteratorX p(q), p=q, ++p, p++, *p=expr ., *p++=expr .,
Forward IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref .
Bidirectional IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref .
Random Access IteratorX p, X p(q), p=q, ++p, p++, p==q, p!=q, *p⇒ ref ., p->m,*p++⇒ ref ., --p, p--, *p--⇒ ref . p<q, p<=q, p>q, p>=q, p+n,p-n, p-q, p+=n, p-=n, p[n]
43 / 155
Concept refinement
Iterator Concepts
TrivialIterator
InputIterator OutputIterator
ForwardIterator
BidirectionalIterator
RandomAccessIterator
Iterators form a hierarchy, or taxonomyMore constraints added when going downwardsNote, another dimension, (im)mutability, ignored here.
44 / 155
Concept refinement
Refinement
Connection between requirements and abstractions:Fewer requirements, more abstractionsMore requirements, fewer abstractions
Gives rise to the notion of refinement between conceptsVisible for example in the iterator concepts
45 / 155
Concept refinement
Refinement: example
Closed plane figure
N sides
. . .
Polygon Concept
Closed plane figure
N sides
Equal side lengths. . .
EquilateralPolygon Concept
. . .refine
46 / 155
Concept refinement
Refinement: example
Output Iterator
Forward Iterator
Bidirectional Iterator
Random Access Iterator
Vector iterator
Input Iterator
Deque iterator
Slist iterator
List iterator
Istream iterator Ostream iterator
47 / 155
Concept refinement
More requirements enables algorithms
Adding more requirements eliminates some models, but...enables new algorithms.Stepanov uses the following analogy:
Concepts correspond to theories in mathematical logic. A theory canbe identified with the set of theorems that are valid in it, or with theset of models that satisfy the theoryConcept can be identified with the set of algorithms that can bewritten based on it, or with the set of data-structures that model it.
48 / 155
Concept refinement
Refinement: new algorithms are enabled along refinement
Container
refine
refine
refine
Forward Container
Random Access Container
enables generic algorithms copy, equal, transform, …
enables find, merge, fill, replace, remove, unique, rotate, max_element, …
enables reverse, partition, rotate, inplace_merge, …
enables sort, binary_search, rotate, random_shuffle, …
RequiresInput Iterators
Forward Iterators
Bidirectional Iterators
Random Access Iterators
Reversible Container
49 / 155
Specifying concepts in C++
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
50 / 155
Specifying concepts in C++
Concepts: specifying requirements
We defined the term concept in a very general manner. This leaves alot of questions:
What does “a set of requirements” mean?How are these requirements described?Is there a formal way?...
⇒ a set of conventions has been established to describe therequirements
51 / 155
Specifying concepts in C++
Concepts: specifying requirements
The elements of the concept description are categorized as follows:
Valid Expressions: C++ expressions that must compilesuccessfully
Expression Semantics: Semantics of the valid expressions.Associated Types: The names of auxiliary types associated with
the concept.Complexity Guarantees: Specifies limits for the resource consumption
(e.g., execution time, memory) of the validexpressions
Invariants: Pre and post-conditions that must always betrue.
Refinements: List of concepts that the current conceptrefines.
52 / 155
Specifying concepts in C++
Example: EqualityComparable
DescriptionA type is EqualityComparable if objects of that type can be compared for equality usingoperator==, and if operator== is an equivalence relation.Refinement ofAssociated typesNotationX A type that is a model of EqualityComparablex, y, z Object of type X
Valid expressionsName Expression Type requirements Return typeEquality x==y Convertible to boolInequality x!=y Convertible to bool
Expression semanticsName Expression Precondition Semantics PostconditionEquality x==y x, y in domain of ==Inequality x!=y x, y in domain of == Equivalent to !(x==y)
Complexity guaranteesInvariantsIdentity &x == &y implies x == yReflexivity x == xSymmetry x == y implies y == xTransitivity x == y and y == z implies x == z
Models int, vector<int>
53 / 155
Specifying concepts in C++
Why so many requirements?
Why do we need !=?Why does == have to be an equivalence relation?Consider find:template<class InputIterator, class EqualityComparable>InputIterator find(InputIterator first, InputIterator last,
const EqualityComparable& value) {while (first != last && !(*first == val))
++first;return first;
}
A generic algorithm must be able to rely on sane semantics of theinput types. One cannot afford to deal with irregularities.The models of concepts must thus do the work of providing allrequired syntax and semantics.Again, concepts are not random collections of requirements.
54 / 155
Specifying concepts in C++
Why so many requirements?
Why do we need !=?Why does == have to be an equivalence relation?Consider find:template<class InputIterator, class EqualityComparable>InputIterator find(InputIterator first, InputIterator last,
const EqualityComparable& value) {while (first != last && *first != val)
++first;return first;
}
A generic algorithm must be able to rely on sane semantics of theinput types. One cannot afford to deal with irregularities.The models of concepts must thus do the work of providing allrequired syntax and semantics.Again, concepts are not random collections of requirements.
54 / 155
Specifying concepts in C++
Why so many requirements?
Why do we need !=?Why does == have to be an equivalence relation?Consider find:template<class InputIterator, class EqualityComparable>InputIterator find(InputIterator first, InputIterator last,
const EqualityComparable& value) {while (first != last && val != *first)
++first;return first;
}
A generic algorithm must be able to rely on sane semantics of theinput types. One cannot afford to deal with irregularities.The models of concepts must thus do the work of providing allrequired syntax and semantics.Again, concepts are not random collections of requirements.
54 / 155
Specifying concepts in C++
Why so many requirements?
Why do we need !=?Why does == have to be an equivalence relation?Consider find:template<class InputIterator, class EqualityComparable>InputIterator find(InputIterator first, InputIterator last,
const EqualityComparable& value) {while (first != last && val != *first)
++first;return first;
}
A generic algorithm must be able to rely on sane semantics of theinput types. One cannot afford to deal with irregularities.The models of concepts must thus do the work of providing allrequired syntax and semantics.Again, concepts are not random collections of requirements.
54 / 155
Specifying concepts in C++
About Equality
Stepanov, Jones:datum — finite sequence of 0s and 1svalue — a datum with an interpretation of a datum as an abstractentity; datum is the representation of the abstract entityExample of a value: rational numbers represented as a concatenationof two 32-bit sequences, interpreted as integer numerator anddenominator, represented as two’s complement little-endian valuesA value type is uniquely represented iff there is at most one valuecorresponding to every particular abstract entity
bool is not uniquely representedA value type is ambiguous iff a value has more than one interpretation
Example: A calendar year represented with two decimal digits
55 / 155
Specifying concepts in C++
... About Equality
Two values (of a value type) are equal iff they represent the sameabstract entititiesTwo values are structurally equal iff their datums are identical
Equality implies structural equality if a value type is uniquelyrepresentedStructural equality implies equality if a value type is not ambiguousFor uniquely represented types, implementation of equality iscomparison of bit sequencesFor other types, implementation of equality must be consistent withinterpretationsNon-unique representations are chosen when testing equality is doneless frequently than operations generating new values and when it ispossible to make generating new values faster at the cost of makingequality slower.
Example: two sets represented as unsorted sequencesWe will return to equality of objects later
56 / 155
Specifying concepts in C++
... About Equality
Two values (of a value type) are equal iff they represent the sameabstract entititiesTwo values are structurally equal iff their datums are identicalEquality implies structural equality if a value type is uniquelyrepresentedStructural equality implies equality if a value type is not ambiguous
For uniquely represented types, implementation of equality iscomparison of bit sequencesFor other types, implementation of equality must be consistent withinterpretationsNon-unique representations are chosen when testing equality is doneless frequently than operations generating new values and when it ispossible to make generating new values faster at the cost of makingequality slower.
Example: two sets represented as unsorted sequencesWe will return to equality of objects later
56 / 155
Specifying concepts in C++
... About Equality
Two values (of a value type) are equal iff they represent the sameabstract entititiesTwo values are structurally equal iff their datums are identicalEquality implies structural equality if a value type is uniquelyrepresentedStructural equality implies equality if a value type is not ambiguousFor uniquely represented types, implementation of equality iscomparison of bit sequencesFor other types, implementation of equality must be consistent withinterpretationsNon-unique representations are chosen when testing equality is doneless frequently than operations generating new values and when it ispossible to make generating new values faster at the cost of makingequality slower.
Example: two sets represented as unsorted sequencesWe will return to equality of objects later
56 / 155
Specifying concepts in C++
... About Equality
Two values (of a value type) are equal iff they represent the sameabstract entititiesTwo values are structurally equal iff their datums are identicalEquality implies structural equality if a value type is uniquelyrepresentedStructural equality implies equality if a value type is not ambiguousFor uniquely represented types, implementation of equality iscomparison of bit sequencesFor other types, implementation of equality must be consistent withinterpretationsNon-unique representations are chosen when testing equality is doneless frequently than operations generating new values and when it ispossible to make generating new values faster at the cost of makingequality slower.
Example: two sets represented as unsorted sequencesWe will return to equality of objects later
56 / 155
Specifying concepts in C++
STL documentation
http://www.sgi.com/tech/stl/
Note! The SGI STL documentation is not the documentation of theC++ standard library
C++ standard library has been, and is, evolving. The SGI STLdocumentation is not being updated to match that.
It is a good source for learning, but not to be used as a final reference
57 / 155
Specifying concepts in C++
More STL documentation
http://www.josuttis.com/libbook/
http://webstore.ansi.org/
http://www.wiley.com/WileyCDA/WileyTitle/productCd-0470846747.html
58 / 155
Specifying concepts in C++
Documenting STL Concepts
Next.... a closer look at some STL’s concept descriptions
59 / 155
Specifying concepts in C++
Trivial Iterator
Description
A Trivial Iterator is an object that may be dereferenced to refer to some other object.Arithmetic operations (such as increment and comparison) are not guaranteed to besupported.
Refinement of
Assignable, Equality Comparable, Default Constructible
60 / 155
Specifying concepts in C++
Trivial Iterator
Definitions
A type that is a model of Trivial Iterator may be mutable, meaning that the valuesreferred to by objects of that type may be modified, or constant, meaning thatthey may not. For example, int* is a mutable iterator type and const int* is aconstant iterator type. If an iterator type is mutable, this implies that its valuetype is a model of Assignable; the converse, though, is not necessarily true.
A Trivial Iterator may have a singular value, meaning that the results of mostoperations, including comparison for equality, are undefined. The only operationthat a is guaranteed to be supported is assigning a nonsingular iterator to asingular iterator.
A Trivial Iterator may have a dereferenceable value, meaning that dereferencing ityields a well-defined value. Dereferenceable iterators are always nonsingular, butthe converse is not true. For example, a null pointer is nonsingular (there are welldefined operations involving null pointers) even though it is not dereferenceable.
Invalidating a dereferenceable iterator means performing an operation after whichthe iterator might be nondereferenceable or singular. For example, if p is a pointer,then delete p invalidates p.
61 / 155
Specifying concepts in C++
Trivial Iterator
Definitions
A type that is a model of Trivial Iterator may be mutable, meaning that the valuesreferred to by objects of that type may be modified, or constant, meaning thatthey may not. For example, int* is a mutable iterator type and const int* is aconstant iterator type. If an iterator type is mutable, this implies that its valuetype is a model of Assignable; the converse, though, is not necessarily true.
A Trivial Iterator may have a singular value, meaning that the results of mostoperations, including comparison for equality, are undefined. The only operationthat a is guaranteed to be supported is assigning a nonsingular iterator to asingular iterator.
A Trivial Iterator may have a dereferenceable value, meaning that dereferencing ityields a well-defined value. Dereferenceable iterators are always nonsingular, butthe converse is not true. For example, a null pointer is nonsingular (there are welldefined operations involving null pointers) even though it is not dereferenceable.
Invalidating a dereferenceable iterator means performing an operation after whichthe iterator might be nondereferenceable or singular. For example, if p is a pointer,then delete p invalidates p.
61 / 155
Specifying concepts in C++
Trivial Iterator
Definitions
A type that is a model of Trivial Iterator may be mutable, meaning that the valuesreferred to by objects of that type may be modified, or constant, meaning thatthey may not. For example, int* is a mutable iterator type and const int* is aconstant iterator type. If an iterator type is mutable, this implies that its valuetype is a model of Assignable; the converse, though, is not necessarily true.
A Trivial Iterator may have a singular value, meaning that the results of mostoperations, including comparison for equality, are undefined. The only operationthat a is guaranteed to be supported is assigning a nonsingular iterator to asingular iterator.
A Trivial Iterator may have a dereferenceable value, meaning that dereferencing ityields a well-defined value. Dereferenceable iterators are always nonsingular, butthe converse is not true. For example, a null pointer is nonsingular (there are welldefined operations involving null pointers) even though it is not dereferenceable.
Invalidating a dereferenceable iterator means performing an operation after whichthe iterator might be nondereferenceable or singular. For example, if p is a pointer,then delete p invalidates p.
61 / 155
Specifying concepts in C++
Trivial Iterator
Definitions
A type that is a model of Trivial Iterator may be mutable, meaning that the valuesreferred to by objects of that type may be modified, or constant, meaning thatthey may not. For example, int* is a mutable iterator type and const int* is aconstant iterator type. If an iterator type is mutable, this implies that its valuetype is a model of Assignable; the converse, though, is not necessarily true.
A Trivial Iterator may have a singular value, meaning that the results of mostoperations, including comparison for equality, are undefined. The only operationthat a is guaranteed to be supported is assigning a nonsingular iterator to asingular iterator.
A Trivial Iterator may have a dereferenceable value, meaning that dereferencing ityields a well-defined value. Dereferenceable iterators are always nonsingular, butthe converse is not true. For example, a null pointer is nonsingular (there are welldefined operations involving null pointers) even though it is not dereferenceable.
Invalidating a dereferenceable iterator means performing an operation after whichthe iterator might be nondereferenceable or singular. For example, if p is a pointer,then delete p invalidates p.
61 / 155
Specifying concepts in C++
Trivial Iterator
Associated types
Value type The type of the value obtained by deref-erencing a Trivial Iterator
Notation
X A type that is a model of Trivial IteratorT The value type of X
x, y Object of type X
t Object of type T
62 / 155
Specifying concepts in C++
Trivial Iterator
Valid expressions
In addition to the expressions defined in Assignable, Equality Comparable, and DefaultConstructible, the following expressions must be valid.Name Expression Type requirements Return typeDefault construc-tor
X x
Dereference *x Convertible to T1
Dereference as-signment
*x = t X is mutable
Member access x->m T is a type for whichx.m is defined
63 / 155
Specifying concepts in C++
Trivial Iterator
Expression semantics
Name Expression Precondition Semantics PostconditionDefault con-structor
X x x is singular
Dereference *x x is derefer-enceable
Dereferenceassignment
*x = t x is derefer-enceable
*x is a copy oft
Memberaccess
x->m x is derefer-enceable
Equivalent to(*x).m
Complexity guarantees
The complexity of operations on trivial iterators is guaranteed to be amortized constanttime.
64 / 155
Specifying concepts in C++
Trivial Iterator
Invariants
Identity x == y if and only if &*x == &*y
Models
A pointer to an object that is not part of an array.
65 / 155
Specifying concepts in C++
Trivial Iterator
Notes
[1] The requirement for the return type of *x is specified as ¨convertible to T¨, ratherthan simply T, because it sometimes makes sense for an iterator to return some sort ofproxy object instead of the object that the iterator conceptually points to. Proxy objectsare implementation details rather than part of an interface (one use of them, forexample, is to allow an iterator to behave differently depending on whether its value isbeing read or written), so the value type of an iterator that returns a proxy is still T.
See also
Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, Random AccessIterator, Iterator Overview
66 / 155
Specifying concepts in C++
About concept descriptions
So far we can observe the following regarding concept descriptionsThey are not part of C++, they are documentationThe documentation is semi-formal, or semi-structured
E.g. valid expressions, associated types, refinementsSome properties are explained just with prose
E.g. Singularity vs. non-singularity
Valid expressions, instead of signature requirementsSyntactic and semantic constraintsComplexity requirements
67 / 155
Specifying concepts in C++
Important aspects of iterators
Mutable/constant iteratorSingular/non-singular iteratorDereferenceable iteratorInvalidating an iterator
Next.... Input Iterator
68 / 155
Specifying concepts in C++
Input Iterator
Description
An Input Iterator is an iterator that may be dereferenced to refer to some object, andthat may be incremented to obtain the next iterator in a sequence. Input Iterators arenot required to be mutable.
Refinement of
Trivial iterator.
69 / 155
Specifying concepts in C++
Input Iterator
Associated types
Value type The type of the value obtained by dereferencing an Input IteratorDistance type A signed integral type used to represent the distance from one iterator
to another, or the number of elements in a range.
Notation
X A type that is a model of Input IteratorT The value type of X
i, j Object of type X
t Object of type T
70 / 155
Specifying concepts in C++
Input Iterator
Definitions
An iterator is past-the-end if it points beyond the last element of a container.Past-the-end values are nonsingular and nondereferenceable.
An iterator is valid if it is dereferenceable or past-the-end.
An iterator i is incrementable if there is a ¨next¨ iterator, that is, if ++i iswell-defined. Past-the-end iterators are not incrementable.
An Input Iterator j is reachable from an Input Iterator i if, after applying operator++
to i a finite number of times, i == j.1
The notation [i,j) refers to a range of iterators beginning with i and up to but notincluding j.
The range [i,j) is a valid range if both i and j are valid iterators, and j is reachablefrom i.2
71 / 155
Specifying concepts in C++
Input Iterator
Definitions
An iterator is past-the-end if it points beyond the last element of a container.Past-the-end values are nonsingular and nondereferenceable.
An iterator is valid if it is dereferenceable or past-the-end.
An iterator i is incrementable if there is a ¨next¨ iterator, that is, if ++i iswell-defined. Past-the-end iterators are not incrementable.
An Input Iterator j is reachable from an Input Iterator i if, after applying operator++
to i a finite number of times, i == j.1
The notation [i,j) refers to a range of iterators beginning with i and up to but notincluding j.
The range [i,j) is a valid range if both i and j are valid iterators, and j is reachablefrom i.2
71 / 155
Specifying concepts in C++
Input Iterator
Definitions
An iterator is past-the-end if it points beyond the last element of a container.Past-the-end values are nonsingular and nondereferenceable.
An iterator is valid if it is dereferenceable or past-the-end.
An iterator i is incrementable if there is a ¨next¨ iterator, that is, if ++i iswell-defined. Past-the-end iterators are not incrementable.
An Input Iterator j is reachable from an Input Iterator i if, after applying operator++
to i a finite number of times, i == j.1
The notation [i,j) refers to a range of iterators beginning with i and up to but notincluding j.
The range [i,j) is a valid range if both i and j are valid iterators, and j is reachablefrom i.2
71 / 155
Specifying concepts in C++
Input Iterator
Definitions
An iterator is past-the-end if it points beyond the last element of a container.Past-the-end values are nonsingular and nondereferenceable.
An iterator is valid if it is dereferenceable or past-the-end.
An iterator i is incrementable if there is a ¨next¨ iterator, that is, if ++i iswell-defined. Past-the-end iterators are not incrementable.
An Input Iterator j is reachable from an Input Iterator i if, after applying operator++
to i a finite number of times, i == j.1
The notation [i,j) refers to a range of iterators beginning with i and up to but notincluding j.
The range [i,j) is a valid range if both i and j are valid iterators, and j is reachablefrom i.2
71 / 155
Specifying concepts in C++
Input Iterator
Definitions
An iterator is past-the-end if it points beyond the last element of a container.Past-the-end values are nonsingular and nondereferenceable.
An iterator is valid if it is dereferenceable or past-the-end.
An iterator i is incrementable if there is a ¨next¨ iterator, that is, if ++i iswell-defined. Past-the-end iterators are not incrementable.
An Input Iterator j is reachable from an Input Iterator i if, after applying operator++
to i a finite number of times, i == j.1
The notation [i,j) refers to a range of iterators beginning with i and up to but notincluding j.
The range [i,j) is a valid range if both i and j are valid iterators, and j is reachablefrom i.2
71 / 155
Specifying concepts in C++
Input Iterator
Definitions
An iterator is past-the-end if it points beyond the last element of a container.Past-the-end values are nonsingular and nondereferenceable.
An iterator is valid if it is dereferenceable or past-the-end.
An iterator i is incrementable if there is a ¨next¨ iterator, that is, if ++i iswell-defined. Past-the-end iterators are not incrementable.
An Input Iterator j is reachable from an Input Iterator i if, after applying operator++
to i a finite number of times, i == j.1
The notation [i,j) refers to a range of iterators beginning with i and up to but notincluding j.
The range [i,j) is a valid range if both i and j are valid iterators, and j is reachablefrom i.2
71 / 155
Specifying concepts in C++
Input Iterator
Valid expressions
In addition to the expressions defined in Trivial Iterator, the following expressions mustbe valid.Name Expression Type requirements Return typePreincrement ++i X&
Postincrement (void)i++
Postincrement anddereference
*i++ T
Complexity guarantees
All operations are amortized constant time.
72 / 155
Specifying concepts in C++
Input Iterator
Invariants
Models
istream_iterator
Notes
[1] i == j does not imply ++i == ++j.[2] Every iterator in a valid range [i, j) is dereferenceable, and j is either dereferenceableor past-the-end. The fact that every iterator in the range is dereferenceable follows fromthe fact that incrementable iterators must be deferenceable.[3] After executing ++i, it is not required that copies of the old value of i bedereferenceable or that they be in the domain of operator==.[4] It is not guaranteed that it is possible to pass through the same input iterator twice.
See also
Output Iterator, Iterator overview
73 / 155
Specifying concepts in C++
Important aspects of iterators
Past-the-end iteratorValid iteratorIncrementable iteratorIterator i reachable from iterator jRange [i, j)
Valid range
74 / 155
Algorithms
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
75 / 155
Algorithms
Framework: algorithms
Once the iterator concepts have been defined, they can be used inspecifications of algorithms
76 / 155
Algorithms
for_each
Category: algorithms Component type: function
Prototype
template <class InputIterator, class UnaryFunction>UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);
Possible Implementation
template <class InputIterator, class UnaryFunction>UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f){
for (InputIterator p = first; p != last; ++p)f(*p);
return f;}
77 / 155
Algorithms
for_each
Category: algorithms Component type: function
Prototype
template <class InputIterator, class UnaryFunction>UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);
Possible Implementation
template <class InputIterator, class UnaryFunction>UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f){
for (InputIterator p = first; p != last; ++p)f(*p);
return f;}
77 / 155
Algorithms
for_each
Description
For_each applies the function object f to each element in the range [first, last); f’s returnvalue, if any, is ignored. Applications are performed in forward order, i.e. from first tolast. For_each returns the function object after it has been applied to each element.1
Definition
Defined in the standard header <algorithm>.
78 / 155
Algorithms
for_each
Requirements on types
InputIterator is a model of Input Iterator
UnaryFunction is a model of Unary Function
UnaryFunction does not apply any non-constant operation through its argument.
InputIterator’s value type is convertible to UnaryFunction’s argument type.
Preconditions
[first, last) is a valid range.
79 / 155
Algorithms
for_each
Complexity
Linear. Exactly last - first applications of UnaryFunction.
Example 1
void print (int x){
std::cout << x << ’ ’;}
int main(){
int A[] = {1, 4, 2, 8, 5, 7};const int N = sizeof(A) / sizeof(int);
std::for_each(A, A + N, &print);}
80 / 155
Algorithms
for_each
Example 2
template<class T> struct print{
print(ostream& out) : os(out) {}void operator() (T x){
os << x << ’ ’;}
ostream& os;};
int main(){
int A[] = {1, 4, 2, 8, 5, 7};const int N = sizeof(A) / sizeof(int);
std::for_each(A, A + N, print<int>(std::cout));}
81 / 155
Algorithms
for_each
Example 3
template<class T> struct print{
print(ostream& out) : os(out), count(0) {}void operator() (T x){
os << x << ’ ’; ++count;}ostream& os; int count;
};
int main(){
int A[] = {1, 4, 2, 8, 5, 7};const int N = sizeof(A) / sizeof(int);
print<int> f = std::for_each(A, A + N, print<int>(std::cout));std::cout << std::endl << f.count << "items." << std::endl;
}
82 / 155
Algorithms
for_each
Notes
[1] This return value is sometimes useful, since a function object may have local state. Itmight, for example, count the number of times that it is called, or it might have a statusflag to indicate whether or not a call succeeded.
See also
The function object overview, count, copy
83 / 155
Algorithms
On specifying the requirements of algorithm’s typeparameters
We can now use the concepts to gain economy of expressionThe name of the type parameter signifies the concept requirement
Note that the name means nothing to the compiler (could be T just aswell)
Concepts do not capture all requirementsAdditional semantic restrictions can be imposedRequirements between two or more type parameters
84 / 155
Algorithms
copy
Category: algorithms Component type: function
Prototype
template <class InputIterator, class OutputIterator>OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
85 / 155
Algorithms
copy
Description
Copy copies elements from the range [first, last) to the range [result, result + (last - first)).That is, it performs the assignments *result = *first, *(result + 1) = *(first + 1), and so on.1
Generally, for every integer n from 0 to last - first, copy performs the assignment*(result + n) = *(first + n). Assignments are performed in forward order, i.e. in order ofincreasing n.2
The return value is result + (last - first)
Definition
Defined in the standard header <algorithm>.
86 / 155
Algorithms
copy
Preconditions
[first, last) is a valid range.
result is not an iterator within the range [first, last).
There is enough space to hold all of the elements being copied. More formally, therequirement is that [result, result + (last - first)) is a valid range.1
Requirements on types
InputIterator is a model of Input Iterator.
OutputIterator is a model of Output Iterator.
InputIterator’s value type is convertible to a type in OutputIterator’s set of valuetypes.
Complexity
Linear. Exactly last - first assignments are performed.87 / 155
Algorithms
copy
Notes
[1] Copy cannot be used directly to insert elements into an empty Container: itoverwrites elements, rather than inserting elements. If you want to insert elementsinto a Sequence, you can either use its insert member function explicitly, or elseyou can use copy along with an insert_iterator adaptor.
[2] The order of assignments matters in the case where the input and outputranges overlap: copy may be used if the end of the output range overlaps with theinput range, but it can not be used if the beginning of the output range overlapswith the input range; use copy_backward in that case. If the two ranges are completelynonoverlapping, then either algorithm may be used. The order of assignments alsomatters if result is an ostream_iterator, or some other iterator whose semanticsdepends on the order or assignments.
See also
copy_backward, copy_n
88 / 155
Algorithms
copy
Notes
[1] Copy cannot be used directly to insert elements into an empty Container: itoverwrites elements, rather than inserting elements. If you want to insert elementsinto a Sequence, you can either use its insert member function explicitly, or elseyou can use copy along with an insert_iterator adaptor.
[2] The order of assignments matters in the case where the input and outputranges overlap: copy may be used if the end of the output range overlaps with theinput range, but it can not be used if the beginning of the output range overlapswith the input range; use copy_backward in that case. If the two ranges are completelynonoverlapping, then either algorithm may be used. The order of assignments alsomatters if result is an ostream_iterator, or some other iterator whose semanticsdepends on the order or assignments.
See also
copy_backward, copy_n
88 / 155
Algorithms
copy
Example
vector<int> V(5);// ...fill the vector...
list<int> L(V.size());copy(V.begin(), V.end(), L.begin());assert(equal(V.begin(), V.end(), L.begin()));
89 / 155
Algorithms
Noteworthy issues
Several definitions from Trivial Iterator and Input Iteratorconcept descriptions are utilized:
range, valid rangeReferences to other concepts
Container, SequenceImportant semantic aspects are, and must be, specified
Order of assignments
90 / 155
Algorithms
transform
Category: algorithms Component type: function
Prototype
Transform is an overloaded name; there are actually two transform functions.
template <class InputIterator, class OutputIterator, class UnaryFunction>OutputIterator transform(InputIterator first, InputIterator last,
OutputIterator result, UnaryFunction op);
template <class InputIterator1, class InputIterator2, class OutputIterator,class BinaryFunction>
OutputIterator transform(InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, OutputIterator result,BinaryFunction binary_op);
91 / 155
Algorithms
transform I
Description
Transform performs an operation on objects; there are two versions of transform, one of whichuses a single range of Input Iterators and one of which uses two ranges of Input Iterators.The first version of transform performs the operation op(*i) for each iterator i in the range[first, last), and assigns the result of that operation to *o, where o is the correspondingoutput iterator. That is, for each n such that 0 <= n < last - first, it performs theassignment *(result + n) = op(*(first + n)). The return value is result + (last - first).The second version of transform is very similar, except that it uses a Binary Functioninstead of a Unary Function: it performs the operation op(*i1, *i2) for each iterator i1 inthe range [first1, last1) and assigns the result to *o, where i2 is the corresponding iteratorin the second input range and where o is the corresponding output iterator. That is, foreach n such that 0 <= n < last1 - first1, it performs the assignment*(result + n) = op(*(first1 + n), *(first2 + n). The return value is result + (last1 - first1).Note that transform may be used to modify a sequence ¨in place¨: it is permissible for theiterators first and result to be the same.1
92 / 155
Algorithms
transform I
Definition
Defined in the standard header <algorithm>.
93 / 155
Algorithms
transform I
Requirements on types
For the first (unary) version:
InputIterator must be a model of Input Iterator.
OutputIterator must be a model of Output Iterator.
UnaryFunction must be a model of Unary Function.
InputIterator’s value type must be convertible to UnaryFunction’s argument type.
UnaryFunction’s result type must be convertible to a type in OutputIterator’s set of valuetypes.
For the second (binary) version:
InputIterator1 and InputIterator2 must be models of Input Iterator.
OutputIterator must be a model of Output Iterator.
BinaryFunction must be a model of Binary Function.
InputIterator1’s and InputIterator2’s value types must be convertible, respectively, toBinaryFunction’s first and second argument types.
94 / 155
Algorithms
transform II
UnaryFunction’s result type must be convertible to a type in OutputIterator’s set of valuetypes.
95 / 155
Algorithms
transform I
Preconditions
For the first (unary) version:
[first, last) is a valid range.
result is not an iterator within the range [first+1, last).1 (cf. Section 8)
There is enough space to hold all of the elements being copied. More formally, therequirement is that [result, result + (last - first)) is a valid range.
For the second (binary) version:
[first1, last1) is a valid range.
[first2, first2 + (last1 - first1)) is a valid range.
result is not an iterator within the range [first1+1, last1) or[first2 + 1, first2 + (last1 - first1)).
There is enough space to hold all of the elements being copied. More formally, therequirement is that [result, result + (last1 - first1)) is a valid range.
96 / 155
Algorithms
transform I
Complexity
Linear. The operation is applied exactly last - first times in the case of the unaryversion, or last1 - first1 in the case of the binary version.
97 / 155
Algorithms
transform I
Example 1
Replace every number in an array with its negative.
double a[] = { 3.14, 2.72, 1.4e12 };
template <class T>struct negate{
T operator()(T const& x) const{
return -x;}
};
std::transform(a, a+sizeof(a)/sizeof(*a), a, negate<double>());
98 / 155
Algorithms
transform I
Example 2
Calculate the sum of two vectors, storing the result in a third vector.template <class T>struct plus{
T operator()(T const& x, T const& y) const{
return x + y;}
};
void sum2(std::vector<int> const& src1,std::vector<int> const& src2,std::vector<int>& dst)
{assert(dst.size() >= src1.size() && dst.size() >= src2.size());transform(
src1.begin(), src1.end(),src2.begin(),src3.begin(), plus<int>());
}
99 / 155
Algorithms
transform I
Notes
[1] The Output Iterator result is not permitted to be the same as any of the InputIterators in the range [first, last), with the exception of first itself. That is:transform(V.begin(), V.end(), V.begin(), fabs) is valid, buttransform(V.begin(), V.end(), V.begin() + 1, fabs) is not.
See also
The function object overview, copy, generate, fill
100 / 155
Algorithms
Noteworthy issues
Iterators are not fool-proofNo range-checkingNo checking that the begin and end iterator even point to the samesequence
101 / 155
Containers
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
102 / 155
Containers
Container
Forward Container
Reversible Container
Random Access Container
Sequence
Front InsertionSequence
Back InsertionSequence
VectorDequeSlist
List
…
103 / 155
Containers
Containers
General ConceptsContainerForward ContainerReversible ContainerRandom Access Container
SequencesSequenceFront Insertion SequenceBack Insertion Sequence
Associative ContainersAssociative ContainerUnique Associative ContainerMultiple Associative ContainerSimple Associative ContainerPair Associative ContainerSorted Associative ContainerHashed Associative Container
104 / 155
Containers
Container
Category: containers Component type: concept
Description
A Container is an object that stores other objects (its elements), and that hasmethods for accessing its elements. In particular, every type that is a model ofContainer has an associated iterator type that can be used to iterate through theContainer’s elements.There is no guarantee that the elements of a Container are stored in any definiteorder; the order might, in fact, be different upon each iteration through theContainer. Nor is there a guarantee that more than one iterator into a Containermay be active at any one time. (Specific types of Containers, such as ForwardContainer, do provide such guarantees.)A Container ¨owns¨ its elements: the lifetime of an element stored in a containercannot exceed that of the Container itself.1
Refinement of
Assignable105 / 155
Containers
Container
Associated types
Value type X::value_type The type of the object stored in a container.The value type must be Assignable, but neednot be DefaultConstructible.2
Iterator type X::iterator The type of iterator used to iterate througha container’s elements. The iterator’s valuetype is expected to be the container’s valuetype. A conversion from the iterator type tothe const iterator type must exist. The iteratortype must be an input iterator.3
Const iterator type X::const_iterator A type of iterator that may be used to examine,but not to modify, a container’s elements.3,4
106 / 155
Containers
Container
Associated types (cont.)
Reference type X::reference A type that behaves as a reference to thecontainer’s value type.5
Const reference type X::const_reference A type that behaves as a const reference tothe container’s value type.5
Pointer type X::pointer A type that behaves as a pointer to the con-tainer’s value type.6
Distance type X::difference_type A signed integral type used to represent thedistance between two of the container’s it-erators. This type must be the same as theiterator’s distance type.2
Size type X::size_type An unsigned integral type that can representany nonnegative value of the container’s dis-tance type.2
107 / 155
Containers
Container I
Notation
X A type that is a model of Containera, b Object of type X
T The value type of X
Definitions
The size of a container is the number of elements it contains. The size is anonnegative number.
The area of a container is the total number of bytes that it occupies. Morespecifically, it is the sum of the elements’ areas plus whatever overhead isassociated with the container itself. If a container’s value type T is a simple type(as opposed to a container type), then the container’s area is bounded above by aconstant times the container’s size times sizeof(T). That is, if a is a container with asimple value type, then a’s area is O(a.size()).
108 / 155
Containers
Container II
A variable sized container is one that provides methods for inserting and/orremoving elements; its size may vary during a container’s lifetime. A fixed sizecontainer is one where the size is constant throughout the container’s lifetime. Insome fixed-size container types, the size is determined at compile time.
109 / 155
Containers
Container
Valid expressions
In addition to the expressions defined in Assignable, EqualityComparable, andLessThanComparable, the following expressions must be valid.Name Expression Return typeBeginning of range a.begin() iterator if a is mutable, const_iterator otherwise4,7
End of range a.end() iterator if a is mutable, const_iterator otherwise4
Size a.size() size_type
Max size a.max_size() size_type
Empty cont. a.empty() Convertible to bool
Swap a.swap(b) void
110 / 155
Containers
Container
Expression semantics
Semantics of an expression is defined only where it differs from, or is not defined in,Assignable, Equality Comparable, or LessThan ComparableExpression Semantics PostconditionX(a) X().size() == a.size(). X() contains a copy of each of a’s ele-
ments.X b(a); b.size() == a.size(). b contains a copy of each of a’s elements.b = a b.size() == a.size(). b contains a copy of each of a’s elements.
111 / 155
Containers
Container
Expression semantics
a.~X() Each of a’s elements is destroyed,and memory allocated for them (ifany) is deallocated.
a.begin() Returns an iterator pointing to thefirst element in the container.7
a.begin() is either dereferenceable orpast-the-end. It is past-the-end ifand only if a.size() == 0.
a.end() Returns an iterator pointing onepast the last element in the con-tainer.
a.end() is past-the-end.
112 / 155
Containers
Container
Expression semantics
a.size() Returns the size of the container,that is, its number of elements.8
a.size() >= 0 && a.size() <= max_size()
a.max_size() Returns the largest size that thiscontainer can ever have.8
a.max_size() >= 0 &&
a.max_size() >= a.size()
a.empty() Equivalent to a.size() == 0. (Butpossibly faster.)
a.swap(b) Equivalent to swap(a,b)9
113 / 155
Containers
Container
Complexity guarantees
The copy constructor, the assignment operator, and the destructor are linear in thecontainer’s size.
begin() and end() are amortized constant time.
size() is linear in the container’s size.10
max_size() and empty() are amortized constant time. If you are testing whether acontainer is empty, you should always write c.empty() instead of c.size() == 0. Thetwo expressions are equivalent, but the former may be much faster.
swap() is amortized constant time.9
114 / 155
Containers
Container
Invariants
Valid range For any container a, [a.begin(), a.end()) is avalid range.11
Range size a.size() is equal to the distance froma.begin() to a.end().
Completeness An algorithm that iterates through therange [a.begin(), a.end()) will pass throughevery element of a.11
Models
vector
115 / 155
Containers
Container
Notes
[1] The fact that the lifetime of elements cannot exceed that of their containermay seem like a severe restriction. In fact, though, it is not. Note that pointersand iterators may be stored in a container. The container, in that case, ¨owns¨the pointers themselves, but not the objects that they point to.
[2] censored—incorrect
[3] censored—tautology
[4] A container’s iterator type and const iterator type may be the same: there is noguarantee that every container must have an associated mutable iterator type. Forexample, set and hash_set define iterator and const_iterator to be the same type.
116 / 155
Containers
Container
Notes
[1] The fact that the lifetime of elements cannot exceed that of their containermay seem like a severe restriction. In fact, though, it is not. Note that pointersand iterators may be stored in a container. The container, in that case, ¨owns¨the pointers themselves, but not the objects that they point to.
[2] censored—incorrect
[3] censored—tautology
[4] A container’s iterator type and const iterator type may be the same: there is noguarantee that every container must have an associated mutable iterator type. Forexample, set and hash_set define iterator and const_iterator to be the same type.
116 / 155
Containers
Container
Notes
[1] The fact that the lifetime of elements cannot exceed that of their containermay seem like a severe restriction. In fact, though, it is not. Note that pointersand iterators may be stored in a container. The container, in that case, ¨owns¨the pointers themselves, but not the objects that they point to.
[2] censored—incorrect
[3] censored—tautology
[4] A container’s iterator type and const iterator type may be the same: there is noguarantee that every container must have an associated mutable iterator type. Forexample, set and hash_set define iterator and const_iterator to be the same type.
116 / 155
Containers
Container
Notes
[5] It is required that the reference type has the same semantics as an ordinaryC++ reference, but it need not actually be an ordinary C++ reference [Ed: well,sorta]. Some implementations, for example, might provide additional referencetypes to support non-standard memory models. Note, however, that ¨smartreferences¨ (user-defined reference types that provide additional functionality) arenot a viable option. It is impossible for a user-defined type to have the samesemantics as C++ references, because... censored—incorrect
[6] As in the case of references5, the pointer type must have the same semanticsas C++ pointers but need not actually be a C++ pointer. censored—not reallyuseful
[7] The iterator type need only be an input iterator, which provides a very weak setof guarantees; in particular, all algorithms on input iterators must be ¨single pass¨.It follows that only a single iterator into a Container may be active at any onetime. This restriction is removed in Forward Container.
[8] In the case of a fixed-size container, size() == max_size().
117 / 155
Containers
Container
Notes
[5] It is required that the reference type has the same semantics as an ordinaryC++ reference, but it need not actually be an ordinary C++ reference [Ed: well,sorta]. Some implementations, for example, might provide additional referencetypes to support non-standard memory models. Note, however, that ¨smartreferences¨ (user-defined reference types that provide additional functionality) arenot a viable option. It is impossible for a user-defined type to have the samesemantics as C++ references, because... censored—incorrect
[6] As in the case of references5, the pointer type must have the same semanticsas C++ pointers but need not actually be a C++ pointer. censored—not reallyuseful
[7] The iterator type need only be an input iterator, which provides a very weak setof guarantees; in particular, all algorithms on input iterators must be ¨single pass¨.It follows that only a single iterator into a Container may be active at any onetime. This restriction is removed in Forward Container.
[8] In the case of a fixed-size container, size() == max_size().
117 / 155
Containers
Container
Notes
[5] It is required that the reference type has the same semantics as an ordinaryC++ reference, but it need not actually be an ordinary C++ reference [Ed: well,sorta]. Some implementations, for example, might provide additional referencetypes to support non-standard memory models. Note, however, that ¨smartreferences¨ (user-defined reference types that provide additional functionality) arenot a viable option. It is impossible for a user-defined type to have the samesemantics as C++ references, because... censored—incorrect
[6] As in the case of references5, the pointer type must have the same semanticsas C++ pointers but need not actually be a C++ pointer. censored—not reallyuseful
[7] The iterator type need only be an input iterator, which provides a very weak setof guarantees; in particular, all algorithms on input iterators must be ¨single pass¨.It follows that only a single iterator into a Container may be active at any onetime. This restriction is removed in Forward Container.
[8] In the case of a fixed-size container, size() == max_size().
117 / 155
Containers
Container
Notes
[5] It is required that the reference type has the same semantics as an ordinaryC++ reference, but it need not actually be an ordinary C++ reference [Ed: well,sorta]. Some implementations, for example, might provide additional referencetypes to support non-standard memory models. Note, however, that ¨smartreferences¨ (user-defined reference types that provide additional functionality) arenot a viable option. It is impossible for a user-defined type to have the samesemantics as C++ references, because... censored—incorrect
[6] As in the case of references5, the pointer type must have the same semanticsas C++ pointers but need not actually be a C++ pointer. censored—not reallyuseful
[7] The iterator type need only be an input iterator, which provides a very weak setof guarantees; in particular, all algorithms on input iterators must be ¨single pass¨.It follows that only a single iterator into a Container may be active at any onetime. This restriction is removed in Forward Container.
[8] In the case of a fixed-size container, size() == max_size().
117 / 155
Containers
Container I
Notes
[9] For any Assignable type, swap can be defined in terms of one copy and and twoassignments [Ed: corrected], each of which, for a container type, is linear in thecontainer’s size. In a sense, then, a.swap(b) is redundant. It exists solely for the sakeof efficiency: for many containers, such as vector and list, it is possible toimplement swap such that its run-time complexity is constant rather than linear. Ifthis is possible for some container type X, then the template specializationswap(X&, X&) can simply be written in terms of X::swap(X&). The implication of this isthat X::swap(X&) should only be defined if there exists such a constant-timeimplementation. Not every container class X need have such a member function,but if the member function exists at all then it is guaranteed to be amortizedconstant time.
[10] For many containers, such as vector and deque, size is O(1). This satisfies therequirement that it be O(N).
118 / 155
Containers
Container II
[11] Although [a.begin(), a.end()) must be a valid range, and must include everyelement in the container, the order in which the elements appear in that range isunspecified. If you iterate through a container twice, it is not guaranteed that theorder will be the same both times. This restriction is removed in ForwardContainer.
119 / 155
Containers
Container
See also
The Iterator overview, Input Iterator, Sequence
120 / 155
Containers
Noteworthy issues
Many associated typesvalue_type, iterator, const_iterator, ...
New definitions: container size, areaRequirements on space complexity
a.begin(), a.end() give rise to a semi-open interval (from firstelement to past-the-end)Interplay of size, max_size, and empty
Goal is to not over-specify. For example, the order of iteration is notfixed.Interplay between container hierarchy and iterator hierarchyNote that really nothing is yet known of what kind of a container wehave at hand!
121 / 155
Containers
Random Access Container
Category: containers Component type: concept
Description
A Random Access Container is a Reversible [or Bidirectional] Container whose iteratortype is a Random Access Iterator. It provides amortized constant time access toarbitrary elements.
Refinement of
Reversible Container
122 / 155
Containers
Random Access Container
Associated types
No additional types beyond those defined in Reversible Container. However, therequirements for the iterator type are strengthened: it must be a Random AccessIterator.
Notation
X A type that is a model of Random AccessContainer
a, b Object of type X
T The value type of X
123 / 155
Containers
Random Access Container
Valid expressions
In addition to the expressions defined in Reversible Container, the following expressionsmust be valid.Name Expression Type requirements Return typeElement access a[n] n is convertible to
size_type
reference if a is mu-table, const_reference
otherwise
Expression semantics
Semantics of an expression is defined only where it is not defined in ReversibleContainer, or where there is additional information.Name Expression Precondition SemanticsElement access a[n] 0 <= n < a.size() Returns the nth el-
ement from the be-ginning of the con-tainer.
124 / 155
Containers
Random Access Container
Complexity guarantees
The run-time complexity of element access is amortized constant time.
Invariants
Element access The element returned by a[n] is the sameas the one obtained by incrementinga.begin() n times and then dereferencingthe resulting iterator.
Models
vectordeque
Notes
See also
The Iterator overview, Random Access Iterator, Sequence125 / 155
Containers
Associative Container
Associative Container
Category: containers Component type: concept
An Associative Container is a variable-sized Container that supports efficientretrieval of elements (values) based on keys. It supports insertion and removal ofelements, but does not provide a mechanism for inserting an element at a specificposition.1
As with all containers, the elements in an Associative Container are of typevalue_type. Additionally, each element in an Associative Container has a key, of typekey_type. In some Associative Containers [e.g. set] the value_type and key_type are thesame: elements are their own keys. In others [e.g. map], the key is some specificpart of the value.
Since elements are stored according to their keys, it is essential that the keyassociated with each element is immutable. This means that an AssociativeContainer’s value type is not Assignable.
126 / 155
Containers
Associative Container
Associative Container
Associative Containers cannot have mutable iterators, because a mutable iteratormust allow assignment. That is, if i is a mutable iterator and t is an object of i’svalue type, then *i = t must be a valid expression.
In Associative Containers where the elements are the keys, the elements arecompletely immutable; the nested types iterator and const_iterator are therefore thesame. Other types of associative containers, however, do have mutable elements,and do provide iterators through which elements can be modified. Pair AssociativeContainers, for example, have two different nested types iterator and const_iterator.Even in this case, iterator is not a mutable iterator: as explained above, it does notprovide the expression *i = t. It is, however, possible to modify an element throughsuch an iterator: if, for example, i is of type map<int, double>, then (*i).second = 3 is avalid expression.
In some associative containers, Unique Associative Containers, it is guaranteedthat no two elements have the same key.2 In other associative containers, MultipleAssociative Containers, multiple elements with the same key are permitted.
127 / 155
Containers
Associative Container
Refinement of
Forward Container, Default Constructible
Associated types
One new type is introduced, in addition to the types defined in the Forward Containerrequirements.Key type X::key_type The type of the key as-
sociated with X::value_type.Note that the key type andvalue type might be thesame.
128 / 155
Containers
Associative Container
Notation
X A type that is a model of Associative Con-tainer
a Object of type X
t Object of type X::value_type
k Object of type X::key_type
p, q Object of type X::iterator
Definitions
If a is an associative container, then p is a valid iterator in a if it is a valid iterator that isreachable from a.begin().If a is an associative container, then [p, q) is a valid range in a if [p, q) is a valid rangeand p is a valid iterator in a.
129 / 155
Containers
Associative Container
Valid expressions
In addition to the expressions defined in Forward Container, the following expressionsmust be valid.Expression Type reqs. Return typeX a;a.erase(k) size_type
a.erase(p) void
a.erase(p, q) void
a.clear() void
a.find(k) iterator if a is mutable, otherwiseconst_iterator
a.count(k) size_type
a.equal_range(k) pair<iterator, iterator> if a is mu-table, otherwise pair<const_iterator,
const_iterator>.
130 / 155
Containers
Associative Container
Expression semantics
Expression Prec. Semantics PostconditionX a; Creates an empty con-
tainer.The size of the con-tainer is 0.
a.erase(k) Destroys all elementswhose key is the sameas k, and removes themfrom a.2 The returnvalue is the numberof elements that wereerased, i.e. the oldvalue of a.count(k).
a.size() is decrementedby a.count(k). a containsno elements with key k.
131 / 155
Containers
Associative Container
Expression semantics
Expression Prec. Semantics Postconditiona.erase(p) p is a dereference-
able iterator in a.Destroys the ele-ment pointed to byp, and removes itfrom a.
a.size() is decre-mented by 1.
a.erase(p, q) [p, q) is a validrange in a.
Destroys the ele-ments in the range[p,q) and removesthem from a.
a.size() is decre-mented by the dis-tance from i to j.
a.clear() Equivalent toa.erase(a.begin(), a.
end())
132 / 155
Containers
Associative Container
Expression semantics
a.find(k) Returns an iterator pointing to anelement whose key is the same ask, or a.end() if no such element ex-ists.
Either the return value is a.end(),or else the return value has a keythat is the same as k.
a.count(k) Returns the number of elements ina whose keys are the same as k.
133 / 155
Containers
Associative Container
Expression semantics
Expression Prec. Semantics Postconditiona.equal_range(k) Returns a pair P such that
[P.first, P.second) is a rangecontaining all elements in a
whose keys are the same ask.3 If no elements have thesame key as k, the returnvalue is an empty range.
The distance between P.first
and P.second is equal to a.count
(k). If p is a dereferenceableiterator in a, then either p liesin the range [P.first, P.second)
, or else *p has a key that isnot the same as k.
134 / 155
Containers
Associative Container
Complexity guarantees
Average complexity for erase key is at most O(log(size()) + count(k)).
Average complexity for erase element is constant time.
Average complexity for erase range is at most O(log(size()) + N), where N is thenumber of elements in the range.
Average complexity for count is at most O(log(size()) + count(k)).
Average complexity for find is at most logarithmic.
Average complexity for equal range is at most logarithmic.
135 / 155
Containers
Associative Container
Invariants
Contiguous storage All elements with the same key are adjacent to each other.That is, if p and q are iterators that point to elements thathave the same key, and if p precedes q, then every element inthe range [p, q) has the same key as every other element.
Immutability of keys Every element of an Associative Container has an immutablekey. Objects may be inserted and erased, but an element in anAssociative Container may not be modified in such a way asto change its key.
Models
set, multiset
hash_set, hash_multiset
map, multimap
hash_map, hash_multimap
136 / 155
Containers
Associative Container
Notes
[1] You can’t insert elements at a specific position because the arrangement ofelements in an associative container is typically a class invariant; elements in aSorted Associative Container, for example, are always stored in ascending order,and elements in a Hashed Associative Container are always stored according to thehash function. It would make no sense to allow the position of an element to bechosen arbitrarily.
[2] Keys are not required to be Equality Comparable: associative containers do notnecessarily use operator== to determine whether two keys are the same. In SortedAssociative Containers, for example, where keys are ordered by a comparisonfunction, two keys are considered to be the same if neither one is less than theother.
[3] Note the implications of equal_range: if two elements have the same key, theremust be no elements with different keys in between them. The requirement thatelements with the same key be stored contiguously is an associative containerinvariant.
137 / 155
Containers
Associative Container
Notes
[1] You can’t insert elements at a specific position because the arrangement ofelements in an associative container is typically a class invariant; elements in aSorted Associative Container, for example, are always stored in ascending order,and elements in a Hashed Associative Container are always stored according to thehash function. It would make no sense to allow the position of an element to bechosen arbitrarily.
[2] Keys are not required to be Equality Comparable: associative containers do notnecessarily use operator== to determine whether two keys are the same. In SortedAssociative Containers, for example, where keys are ordered by a comparisonfunction, two keys are considered to be the same if neither one is less than theother.
[3] Note the implications of equal_range: if two elements have the same key, theremust be no elements with different keys in between them. The requirement thatelements with the same key be stored contiguously is an associative containerinvariant.
137 / 155
Containers
Associative Container
Notes
[1] You can’t insert elements at a specific position because the arrangement ofelements in an associative container is typically a class invariant; elements in aSorted Associative Container, for example, are always stored in ascending order,and elements in a Hashed Associative Container are always stored according to thehash function. It would make no sense to allow the position of an element to bechosen arbitrarily.
[2] Keys are not required to be Equality Comparable: associative containers do notnecessarily use operator== to determine whether two keys are the same. In SortedAssociative Containers, for example, where keys are ordered by a comparisonfunction, two keys are considered to be the same if neither one is less than theother.
[3] Note the implications of equal_range: if two elements have the same key, theremust be no elements with different keys in between them. The requirement thatelements with the same key be stored contiguously is an associative containerinvariant.
137 / 155
Containers
Noteworthy issues
Division to sequences, associative containers, and other containersNon-modifiable keys in associated containers
138 / 155
Container classes
Container concept models
STL provides data structures that model the various containerconcepts
139 / 155
Container classes
Sequence Classes
vector
list
slist
deque
140 / 155
Container classes
Associative Container Classes
set
map
multiset
multimap
hash_set
hash_map
hash_multiset
hash_multimap
141 / 155
Container classes
Container Adaptor Classes
stack
queue
priority_queue
142 / 155
Example of STL use
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
143 / 155
Example of STL use
Example: simple grep
Write a program to find a text pattern in a specified text file
$> simplegrep main main.cppint main(int argc, char* argv[])
144 / 155
Example of STL use
Example: simple grep
Initiate searchstd::search(
line.begin(), line.end(), pattern.begin(), pattern.end())
Search all linesstd::string line;while (std::getline(ifs, line)){
if ( std::search(line.begin(), line.end(), pattern.begin(), pattern.end()) != line.end() )
{std::cout << line << std::endl;
}}
145 / 155
Example of STL use
Example: simple grep
Process program optionsif (argc != 3){
std::cout << "Usage: " << argv[0] << " string filename"<< std::endl;
return -1;}
std::string pattern(argv[1]);std::ifstream ifs(argv[2]);
Open fileif (!ifs.is_open()){
std::cout << "could not open " << argv[2] << std::endl;return -1;
}
146 / 155
Example of STL use
Example: simple grep
Finish up
ifs.close();return 0;
Headers
#include <iostream>#include <fstream>#include <string>#include <vector>#include <algorithm>#include <iterator>
147 / 155
Example of STL use
Example: simple grep: the whole thing
#include <iostream>#include <fstream>#include <string>#include <vector>#include <algorithm>#include <iterator>
int main(int argc, char∗ argv[]){
if (argc != 3){std::cout << "Usage: " << argv[0] << " string
filename"<< std::endl;
return −1;}
std::string pattern(argv[1]);std::ifstream ifs(argv[2]);if (!ifs.is_open())
{std::cout << "could not open " << argv[2] << std::
endl;return −1;
}std::string line;while (std::getline(ifs, line)){if ( std::search(
line.begin(), line.end(), pattern.begin(), pattern.end()
) != line.end() ){std::cout << line << std::endl;
}}ifs.close();return 0;
}
148 / 155
Example of STL use
Simple binary grep: Searching
struct stat sb;(void) fstat(fd, &sb);unsigned char *ptr =
(unsigned char*)mmap(0, sb.st_size, PROT_READ, MAP_FILE, fd, 0);
149 / 155
Example of STL use
Simple binary rep: Searching
unsigned char* found= std::search(ptr, ptr + sb.st_size, bytes, bytes + nbytes);
if (found != ptr + sb.st_size){
std::cout << "found at " << found - ptr<< std::endl;
}else{
std::cout << "not found" << std::endl;}
150 / 155
Example of STL use
Example: Simple binary Grep
#include <fcntl.h>#include <sys/types.h>#include <sys/mman.h>#include <sys/stat.h>#include <iostream>#include <fstream>#include <string>#include <vector>#include <algorithm>#include <iterator>
unsigned char bytes[] = { 10, 20, 30 };
int main(int argc, char∗ argv[]){
if (argc != 2){std::cout << "Usage: " << argv[0]
<< " filename" << std::endl;return −1;
}
int fd;if ((fd = open(argv[1], 0, O_RDONLY)) == −1){std::cout << "problem" << std::endl;return −1;
}
int nbytes = sizeof(bytes) / sizeof(unsigned char);
struct stat sb;(void) fstat(fd, &sb);unsigned char ∗ptr =(unsigned char∗)mmap(
0, sb.st_size, PROT_READ, MAP_FILE, fd, 0);
unsigned char∗ found= std::search(ptr, ptr + sb.st_size, bytes, bytes +
nbytes);
if (found != ptr + sb.st_size){std::cout << "found at " << found − ptr
<< std::endl;}else{std::cout << "not found" << std::endl;
}
close(fd);return 0;
}
151 / 155
Example of STL use
Grep runs
$> sgrep.exe main sgrep.cpp
int main(int argc, char* argv[])
$> sbgrep.exe main sbgrep.exe
152 / 155
Summary
Outline
1 Introduction & History
2 Polymorphism
3 Generic programming process → STL
4 Concepts
5 Concept refinement
6 Specifying concepts in C++
7 Algorithms
8 Containers
9 Container classes
10 Example of STL use
11 Summary
153 / 155
Summary
Summarizing STL thus far
STL uses a structured way of describing requirements as conceptsThe taxonomy of concepts (refinement hierarchies) are a crucial partof the STLConcepts themselves are reusable elements, requirement are almostinvariably described in terms of conceptsImportant STL components: algorithms, data structures, iterators.Mix and match freely (within constraints), iterators are the glue
From N ×M problem to N + M problem
154 / 155
Summary
Quote
The amazing thing is that many different algorithms need thesame set of requirements and there are multiple implementationsof these requirements. The analogous fact in mathematics is thatmany different theorems depend on the same set of axioms andthere are many different models of the same axioms. Abstractionworks! [Stepanov]
155 / 155