Tải bản đầy đủ (.pdf) (102 trang)

The C++ Programming Language Third Edition phần 6 pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (364.96 KB, 102 trang )

Section 17.6.2.1

Lookup

501

// not found:
i f (b si ze
if b.s iz e()*m ax _l oa d < v si ze
ma x_ lo ad v.s iz e()) { // if ‘‘too full’’
r es iz e(b si ze
re si ze b.s iz e()*g ro w);
gr ow
// grow
r et ur n o pe ra to r[](k ;
re tu rn op er at or
k)
// rehash
}
v pu sh _b ac k(E nt ry k,d ef au lt _v al ue b[i
v.p us h_ ba ck En tr y(k de fa ul t_ va lu e,b i]));
b i] = &v ba ck ;
b[i
v.b ac k()

// add Entry
// point to new element

r et ur n b i]->v al
re tu rn b[i
va l;


}

Unlike m ap h as h_ ma p doesn’t rely on an equality test synthesized from a less-than operation
ma p, ha sh _m ap
(§17.1.4.1). This is because of the call of e q() in the loop that looks through elements with the
eq
same hash value. This loop is crucial to the performance of the lookup, and for common and obvious key types such as s tr in g and C-style strings, the overhead of an extra comparison could be sigst ri ng
nificant.
I could have used a s et En tr y> to represent the set of values that have the same hash value.
se tHowever, if we have a good hash function (h as h()) and an appropriately-sized hash table (b most
ha sh
b),
such sets will have exactly one element. Consequently, I linked the elements of that set together
using the n ex t field of E nt ry (§17.8[27]).
ne xt
En tr y
Note that b keeps pointers to elements of v and that elements are added to v In general,
v.
p us h_ ba ck
pu sh _b ac k() can cause reallocation and thus invalidate pointers to elements (§16.3.5). However,
in this case constructors (§17.6.2) and r es iz e() carefully r es er ve enough space so that no unexre si ze
re se rv e()
pected reallocation happens.
17.6.2.2 Erase and Rehash [cont.hash.erase]
Hashed lookup becomes inefficient when the table gets too full. To lower the chance of that happening, the table is automatically r es iz e()d by the subscript operator. The s et _l oa d() (§17.6.2)
re si ze
se t_ lo ad
provides a way of controlling when and how resizing happens. Other functions are provided to
allow a programmer to observe the state of a h as h_ ma p:

ha sh _m ap
t em pl at ete mp la te cl as s Ke y, cl as s T, cl as s
Ha sh Ke y>,
c la ss E Q = e qu al _t ocl as s EQ eq ua l_ to Ke y>, c la ss A = a ll oc at or T> >
cl as s
al lo ca to rc la ss h as h_ ma p {
cl as s ha sh _m ap
// ...
v oi d r es iz e(s iz e_ ty pe n ;
vo id re si ze si ze _t yp e n)

// make the size of the hash table n

v oi d e ra se it er at or p os it io n);
vo id er as e(i te ra to r po si ti on

// erase the element pointed to

s iz e_ ty pe s iz e() c on st { r et ur n v si ze
si ze _t yp e si ze
co ns t re tu rn v.s iz e()-n o_ of _e ra se d; } // number of elements
no _o f_ er as ed
s iz e_ ty pe b uc ke t_ co un t() c on st { r et ur n b si ze ; }
si ze _t yp e bu ck et _c ou nt
co ns t re tu rn b.s iz e()

// size of hash table


H as he r h as h_ fu n() c on st { r et ur n h as h; }
Ha sh er ha sh _f un
co ns t re tu rn ha sh
k ey _e qu al k ey _e q() c on st { r et ur n e q; }
ke y_ eq ua l ke y_ eq
co ns t re tu rn eq

// hash function used
// equality used

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


502

Standard Containers

Chapter 17

// ...
};

The r es iz e() operation is essential, reasonably simple, and potentially expensive:
re si ze
t em pl at ete mp la te cl as s Ke y, cl as s T, cl as s
Ha sh Ke y>,
c la ss E Q = e qu al _t o

cl as s EQ eq ua l_ to Ke y>, c la ss A = a ll oc at or T> >
cl as s
al lo ca to rv oi d h as h_ ma p::r es iz e(s iz e_ ty pe s
vo id ha sh _m ap re si ze si ze _t yp e s)
{
i f (s <= b si ze
if s
b.s iz e()) r et ur n;
re tu rn
b re si ze s);
b.r es iz e(s
// add s-b.size() pointers
b cl ea r();
b.c le ar
v re se rv e(s ma x_ lo ad ; // if v needs to reallocate, let it happen now
v.r es er ve s*m ax _l oa d)
i f (n o_ of _e ra se d) { // really remove erased elements
if no _o f_ er as ed
f or (s iz e_ ty pe i = v si ze
fo r si ze _t yp e
v.s iz e()-1 0 i; i
1; 0<=i i--)
i f (v i].e ra se d) {
if v[i er as ed
v er as e(&v i]);
v.e ra se v[i
i f (--n o_ of _e ra se d == 0 b re ak
if
no _o f_ er as ed

0) br ea k;
}
}
f or (s iz e_ ty pe i = 0 i v.s iz e(); i
fo r si ze _t yp e
0; ii++) {
s iz e_ ty pe i i = h as h(v i].k ey b.s iz e();
si ze _t yp e ii ha sh v[i ke y)%b si ze
v i].n ex t = b ii ;
v[i ne xt b[i i]
b ii = &v i];
b[i i]
v[i
}

// rehash:
// hash
// link

}

If necessary, a user can ‘‘manually’’ call r es iz e() to ensure that the cost is incurred at a predictable
re si ze
time. I have found a r es iz e() operation important in some applications, but it is not fundamental
re si ze
to the notion of hash tables. Some implementation strategies don’t need it.
All of the real work is done elsewhere (and only if a h as h_ ma p is resized) , so e ra se
ha sh _m ap
er as e() is trivial:

t em pl at ete mp la te cl as s Ke y, cl as s T, cl as s
Ha sh Ke y>,
c la ss E Q = e qu al _t ocl as s EQ eq ua l_ to Ke y>, c la ss A = a ll oc at or T> >
cl as s
al lo ca to rv oi d h as h_ ma p::e ra se it er at or p
vo id ha sh _m ap er as e(i te ra to r p) // erase the element pointed to
{
i f (p er as ed == f al se n o_ of _e ra se d++;
if p->e ra se d
fa ls e) no _o f_ er as ed
p er as ed = t ru e;
p->e ra se d tr ue
}

17.6.2.3 Hashing [cont.hasher]
To complete h as h_ ma p::o pe ra to r[](), we need to define h as h() and e q(). For reasons that
ha sh _m ap op er at or
ha sh
eq
will become clear in §18.4, a hash function is best defined as o pe ra to r()() for a function object:
op er at or
t em pl at e te mp la te cl as s T> st ru ct Ha sh un ar y_ fu nc ti on T, si ze _t
s iz e_ t o pe ra to r()(c on st T k ey c on st
si ze _t op er at or
co ns t T& ke y) co ns t;
};


The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 17.6.2.3

Hashing

503

A good hash function takes a key and returns an integer so that different keys yield different integers with high probability. Choosing a good hash function is an art. However, exclusive-or’ing the
bits of the key’s representation into an integer is often acceptable:
t em pl at e te mp la te cl as s T> si ze _t Ha sh T>: op er at or
co ns t T& ke y) co ns t
{
s iz e_ t r es = 0
si ze _t re s 0;
s iz e_ t l en = s iz eo f(T ;
si ze _t le n si ze of T)
c on st c ha r* p = r ei nt er pr et _c as t<c on st c ha r*>(&k ey ;
co ns t ch ar
re in te rp re t_ ca st co ns t ch ar
ke y)
w hi le (l en
wh il e le n--) r es = (r es 1)^*p
re s
re s<<1
p++; // use bytes of key’s representation

r et ur n r es
re tu rn re s;
}

The use of r ei nt er pr et _c as t (§6.2.7) is a good indication that something unsavory is going on and
re in te rp re t_ ca st
that we can do better in cases when we know more about the object being hashed. In particular, if
an object contains a pointer, if the object is large, or if the alignment requirements on members
have left unused space (‘‘holes’’) in the representation, we can usually do better (see §17.8[29]).
A C-style string is a pointer (to the characters), and a s tr in g contains a pointer. Consequently,
st ri ng
specializations are in order:
s iz e_ t H as h<c ha r*>::o pe ra to r()(c on st c ha r* k ey c on st
si ze _t Ha sh ch ar
op er at or
co ns t ch ar ke y) co ns t
{
s iz e_ t r es = 0
si ze _t re s 0;
w hi le (*k ey r es = (r es 1)^*k ey
wh il e
ke y) re s
re s<<1
ke y++;
r et ur n r es
re tu rn re s;

// use int value of characters

}

t em pl at e te mp la te cl as s C>
s iz e_ t H as h< b as ic _s tr in g<C >::o pe ra to r()(c on st b as ic _s tr in gsi ze _t Ha sh ba si c_ st ri ng C>
op er at or
co ns t ba si c_ st ri ng C>& k ey c on st
ke y) co ns t
{
s iz e_ t r es = 0
si ze _t re s 0;
t yp ed ef b as ic _s tr in gty pe de f ba si c_ st ri ng C>: co ns t_ it er at or CI
C I p = k ey be gi n();
CI
ke y.b eg in
C I e nd = k ey en d();
CI en d ke y.e nd
w hi le (p en d) r es = (r es 1)^*p
wh il e p!=e nd re s
re s<<1
p++;
r et ur n r es
re tu rn re s;

// use int value of characters

}

An implementation of h as h_ ma p will include hash functions for at least integer and string keys.
ha sh _m ap

For more adventurous key types, the user may have to help out with suitable specializations.
Experimentation supported by good measurement is essential when choosing a hash function. Intuition tends to work poorly in this area.
To complete the h as h_ ma p, we need to define the iterators and a minor host of trivial functions;
ha sh _m ap
this is left as an exercise (§17.8[34]).

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


504

Standard Containers

Chapter 17

17.6.3 Other Hashed Associative Containers [cont.hash.other]
For consistency and completeness, the h as h_ ma p should have matching h as h_ se t,
ha sh _m ap
ha sh _s et
h as h_ mu lt im ap and h as h_ mu lt is et Their definitions are obvious from those of h as h_ ma p, m ap
ha sh _m ul ti ma p,
ha sh _m ul ti se t.
ha sh _m ap ma p,
m ul ti ma p, s et and m ul ti se t, so I leave these as an exercise (§17.8[34]). Good public domain and
mu lt im ap se t,
mu lt is et
commercial implementations of these hashed associative containers are available. For real programs, these should be preferred to locally concocted versions, such as mine.

17.7 Advice [cont.advice]

[1] By default, use v ec to r when you need a container; §17.1.
ve ct or
[2] Know the cost (complexity, big-O measure) of every operation you use frequently; §17.1.2.
[3] The interface, implementation, and representation of a container are distinct concepts. Don’t
confuse them; §17.1.3.
[4] You can sort and search according to a variety of criteria; §17.1.4.1.
[5] Do not use a C-style string as a key unless you supply a suitable comparison criterion;
§17.1.4.1.
[6] You can define a comparison criteria so that equivalent, yet different, key values map to the
same key; §17.1.4.1.
[7] Prefer operations on the end of a sequence (b ac k-operations) when inserting and deleting eleba ck
ments; §17.1.4.1.
[8] Use l is t when you need to do many insertions and deletions from the front or the middle of a
li st
container; §17.2.2.
[9] Use m ap or m ul ti ma p when you primarily access elements by key; §17.4.1.
ma p mu lt im ap
[10] Use the minimal set of operations to gain maximum flexibility; §17.1.1
[11] Prefer a m ap to a h as h_ ma p if the elements need to be kept in order; §17.6.1.
ma p
ha sh _m ap
[12] Prefer a h as h_ ma p to a m ap when speed of lookup is essential; §17.6.1.
ha sh _m ap
ma p
[13] Prefer a h as h_ ma p to a m ap if no less-than operation can be defined for the elements; §17.6.1.
ha sh _m ap
ma p
[14] Use f in d() when you need to check if a key is in an associative container; §17.4.1.6.
fi nd
[15] U se e qu al _r an ge to find all elements of a given key in an associative container; §17.4.1.6.

Us e eq ua l_ ra ng e()
[16] Use m ul ti ma p when several values need to be kept for a single key; §17.4.2.
mu lt im ap
[17] Use s et or m ul ti se t when the key itself is the only value you need to keep; §17.4.3.
se t mu lt is et

17.8 Exercises [cont.exercises]
The solutions to several exercises for this chapter can be found by looking at the source text of an
implementation of the standard library. Do yourself a favor: try to find your own solutions before
looking to see how your library implementer approached the problems. Then, look at your
implementation’s version of the containers and their operations.
1. (∗2.5) Understand the O
O() notation (§17.1.2). Do some measurements of operations on standard containers to determine the constant factors involved.
2. (∗2) Many phone numbers don’t fit into a l on g. Write a p ho ne _n um be r type and a class that
lo ng
ph on e_ nu mb er
provides a set of useful operations on a container of p ho ne _n um be rs
ph on e_ nu mb er s.

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 17.8

Exercises

505

3. (∗2) Write a program that lists the distinct words in a file in alphabetical order. Make two versions: one in which a word is simply a whitespace-separated sequence of characters and one in

which a word is a sequence of letters separated by any sequence of non-letters.
4. (∗2.5) Implement a simple solitaire card game.
5. (∗1.5) Implement a simple test of whether a word is a palindrome (that is, if its representation is
symmetric; examples are a da o tt o, and t ut Implement a simple test of whether an integer is a
ad a, ot to
tu t).
palindrome. Implement a simple test of a whether sentence is a palindrome. Generalize.
6. (∗1.5) Define a queue using (only) two s ta ck
st ac ks.
7. (∗1.5) Define a stack similar to s ta ck (§17.3.1), except that it doesn’t copy its underlying const ac k
tainer and that it allows iteration over its elements.
8. (∗3) Your computer will have support for concurrent activities through the concept of a thread,
task, or process. Figure out how that is done. The concurrency mechanism will have a concept
of locking to prevent two tasks accessing the same memory simultaneously. Use the machine’s
locking mechanism to implement a lock class.
9. (∗2.5) Read a sequence of dates such as D ec 85 D ec 50 J an 76 etc., from input and then output
De c8 5, De c5 0, Ja n7 6,
them so that later dates come first. The format of a date is a three-letter month followed by a
two-digit year. Assume that all the years are from the same century.
10. (∗2.5) Generalize the input format for dates to allow dates such as D ec 19 85 1 2/3 19 90
De c1 98 5, 12 3/1 99 0,
(D ec 30 19 50 3 6/2 00 1, etc. Modify exercise §17.8[9] to cope with the new formats.
De c,3 0,1 95 0), 3/6 20 01
11. (∗1.5) Use a b it se t to print the binary values of some numbers, including 0 1 -1 1 8, -1 8, and
bi ts et
0, 1, 1, 18 18
the largest positive i nt
in t.
12. (∗1.5) Use b it se t to represent which students in a class were present on a given day. Read the
bi ts et

b it se ts for a series of 12 days and determine who was present every day. Determine which stubi ts et
dents were present at least 8 days.
13. (∗1.5) Write a L is t of pointers that d el et es the objects pointed to when it itself is destroyed or if
Li st
de le te
the element is removed from the L is t.
Li st
14. (∗1.5) Given a s ta ck object, print its elements in order (without changing the value of the stack).
st ac k
15. (∗2.5) Complete h as h_ ma p (§17.6.1). This involves implementing f in d() and e qu al _r an ge
ha sh _m ap
fi nd
eq ua l_ ra ng e()
and devising a way of testing the completed template. Test h as h_ ma p with at least one key
ha sh _m ap
type for which the default hash function would be unsuitable.
16. (∗2.5) Implement and test a list in the style of the standard l is t.
li st
17. (∗2) Sometimes, the space overhead of a l is t can be a problem. Write and test a singly-linked
li st
list in the style of a standard container.
18. (∗2.5) Implement a list that is like a standard l is t, except that it supports subscripting. Compare
li st
the cost of subscripting for a variety of lists to the cost of subscripting a v ec to r of the same
ve ct or
length.
19. (∗2) Implement a template function that merges two containers.
20. (∗1.5) Given a C-style string, determine whether it is a palindrome. Determine whether an initial sequence of at least three words in the string is a palindrome.
21. (∗2) Read a sequence of (n am e,v al ue
na me va lu e) pairs and produce a sorted list of

(n am e,t ot al me an me di an 4-tuples. Print that list.
na me to ta l,m ea n,m ed ia n)
22. (∗2.5) Determine the space overhead of each of the standard containers on your implementation.
23. (∗3.5) Consider what would be a reasonable implementation strategy for a h as h_ ma p that
ha sh _m ap
needed to use minimal space. Consider what would be a reasonable implementation strategy for

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


506

Standard Containers

Chapter 17

a h as h_ ma p that needed to use minimal lookup time. In each case, consider what operations
ha sh _m ap
you might omit so as to get closer to the ideal (no space overhead and no lookup overhead,
respectively). Hint: There is an enormous literature on hash tables.
24. (∗2) Devise a strategy for dealing with overflow in h as h_ ma p (different values hashing to the
ha sh _m ap
same hash value) that makes e qu al _r an ge trivial to implement.
eq ua l_ ra ng e()
25. (∗2.5) Estimate the space overhead of a h as h_ ma p and then measure it. Compare the estimate
ha sh _m ap
to the measurements. Compare the space overhead of your h as h_ ma p and your
ha sh _m ap
implementation’s m ap

ma p.
26. (∗2.5) Profile your h as h_ ma p to see where the time is spent. Do the same for your
ha sh _m ap
implementation’s m ap and a widely-distributed h as h_ ma p.
ma p
ha sh _m ap
27. (∗2.5) Implement a h as h_ ma p based on a v ec to rha sh _m ap
ve ct or ma p<K V>*> so that each m ap holds all
ma p
keys that have the same hash value.
28. (∗3) Implement a h as h_ ma p using Splay trees (see D. Sleator and R. E. Tarjan: Self-Adjusting
ha sh _m ap
Binary Search Trees, JACM, Vol. 32. 1985).
29. (∗2) Given a data structure describing a string-like entity:
s tr uc t S t {
st ru ct St
i nt s iz e;
in t si ze
c ha r t yp e_ in di ca to r;
ch ar ty pe _i nd ic at or
c ha r* b uf
ch ar bu f;
// point to size characters
s t(c on st c ha r* p ; // allocate and fill buf
st co ns t ch ar p)
};

Create 1000 S ts and use them as keys for a h as h_ ma p. Devise a program to measure the perSt
ha sh _m ap

formance of the h as h_ ma p. Write a hash function (a H as h; §17.6.2.3) specifically for S t keys.
ha sh _m ap
Ha sh
St
30. (∗2) Give at least four different ways of removing the e ra se d elements from a h as h_ ma p. You
er as ed
ha sh _m ap
should use a standard library algorithm (§3.8, Chapter 18) to avoid an explicit loop.
31. (∗3) Implement a h as h_ ma p that erases elements immediately.
ha sh _m ap
32. (∗2) The hash function presented in §17.6.2.3 doesn’t always consider all of the representation
of a key. When will part of a representation be ignored? Write a hash function that always considers all of the representations of a key. Give an example of when it might be wise to ignore
part of a key and write a hash function that computes its value based only on the part of a key
considered relevant.
33. (∗2.5) The code of hash functions tends to be similar: a loop gets more data and then hashes it.
Define a H as h (§17.6.2.3) that gets its data by repeatedly calling a function that a user can
Ha sh
define on a per-type basis. For example:
s iz e_ t r es = 0
si ze _t re s 0;
w hi le (s iz e_ t v = h as h(k ey
wh il e si ze _t
ha sh ke y)) r es = (r es 3)^v
re s
re s<<3 v;

Here, a user can define h as h(K for each type K that needs to be hashed.
ha sh K)
34. (∗3) Given some implementation of h as h_ ma p, implement h as h_ mu lt im ap h as h_ se t, and
ha sh _m ap

ha sh _m ul ti ma p, ha sh _s et
h as h_ mu lt is et
ha sh _m ul ti se t.
35. (∗2.5) Write a hash function intended to map uniformly distributed i nt values into hash values
in t
intended for a table size of about 1024. Given that function, devise a set of 1024 key values, all
of which map to the same value.

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


________________________________________
________________________________________________________________________________________________________________________________________________________________

18
________________________________________
________________________________________________________________________________________________________________________________________________________________

Algorithms and Function Objects
Form is liberating.
– engineers´ proverb

Introduction — overview of standard algorithms — sequences — function objects —
predicates — arithmetic objects — binders — member function objects — f or _e ac h —
fo r_ ea ch
finding elements — c ou nt — comparing sequences — searching — copying — t ra ns co un t
tr an sf or m — replacing and removing elements — filling a sequence — reordering — s wa p
fo rm
sw ap

— sorted sequences — b in ar y_ se ar ch — m er ge — set operations — m in and m ax
bi na ry _s ea rc h
me rg e
mi n
ma x—
heaps — permutations — C-style algorithms — advice — exercises.

18.1 Introduction [algo.intro]
A container by itself is really not that interesting. To be genuinely useful, a container must be supported by basic operations such as finding its size, iterating, copying, sorting, and searching for elements. Fortunately, the standard library provides algorithms to serve the most common and basic
needs that users have of containers.
This chapter summarizes the standard algorithms and gives a few examples of their uses, a presentation of the key principles and techniques used to express the algorithms in C++, and a more
detailed explanation of a few key algorithms.
Function objects provide a mechanism through which a user can customize the behavior of the
standard algorithms. Function objects supply key information that an algorithm needs in order to
operate on a user’s data. Consequently, emphasis is placed on how function objects can be defined
and used.

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


508

Algorithms and Function Objects

Chapter 18

18.2 Overview of Standard Library Algorithms [algo.summary]
At first glimpse, the standard library algorithms can appear overwhelming. However, there are just
60 of them. I have seen classes with more member functions. Furthermore, many algorithms share

a common basic behavior and a common interface style that eases understanding. As with language features, a programmer should use the algorithms actually needed and understood – and only
those. There are no awards for using the highest number of standard algorithms in a program. Nor
are there awards for using standard algorithms in the most clever and obscure way. Remember, a
primary aim of writing code is to make its meaning clear to the next person reading it – and that
person just might be yourself a few years hence. On the other hand, when doing something with
elements of a container, consider whether that action could be expressed as an algorithm in the style
of the standard library. That algorithm might already exist. If you don’t consider work in terms of
general algorithms, you will reinvent the wheel.
Each algorithm is expressed as a template function (§13.3) or a set of template functions. In
that way, an algorithm can operate on many kinds of sequences containing elements of a variety of
types. Algorithms that return an iterator (§19.1) as a result generally use the end of an input
sequence to indicate failure. For example:
v oi d f li st st ri ng
vo id f(l is t<s tr in g>& l s)
ls
{
l is t<s tr in g>::c on st _i te ra to r p = f in d(l s.b eg in ,l s.e nd ,"F re d");
li st st ri ng
co ns t_ it er at or
fi nd ls be gi n() ls en d() Fr ed
i f (p == l s.e nd
if p
ls en d()) {
// didn’t find "Fred"
}
e ls e {
el se
// here, p points to "Fred"
}
}


The algorithms do not perform range checking on their input or output. Range errors must be prevented by other means (§18.3.1, §19.3). When an algorithm returns an iterator, that iterator is of
the same type as one of its inputs. In particular, an algorithm’s arguments control whether it
returns a c on st _i te ra to r or a non-c on st i te ra to r. For example:
co ns t_ it er at or
co ns t it er at or
v oi d f li st in t>& l i, c on st l is t<s tr in g>& l s)
vo id f(l is tli co ns t li st st ri ng
ls
{
l is tli st in t>: it er at or
fi nd li be gi n() li en d() 42
l is t<s tr in g>::c on st _i te ra to r q = f in d(l s.b eg in ,l s.e nd ,"R in g");
li st st ri ng
co ns t_ it er at or
fi nd ls be gi n() ls en d() Ri ng
}

The algorithms in the standard library cover the most common general operations on containers
such as traversals, sorting, searching, and inserting and removing elements. The standard algorithms are all in the s td namespace and their declarations are found in st d
al go ri th m>.
most of the really common algorithms are so simple that the template functions are typically inline.
This implies that the loops expressed by the algorithms benefit from aggressive per-function optimization.
The standard function objects are also in namespace s td but their declarations are found in
st d,
<f un ct io na l>. The function objects are designed to be easy to inline.
fu nc ti on al


The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 18.2

Overview of Standard Library Algorithms

509

Nonmodifying sequence operations are used to extract information from a sequence or to find
the positions of elements in a sequence:
___________________________________________________________________

Nonmodifying Sequence Operations (§18.5) <algorithm>
___________________________________________________________________
___________________________________________________________________

f or _e ac h( )
fo r_ ea ch ()
Do operation for each element in a sequence.


f in d( )
fi nd ()
Find first occurrence of a value in a sequence.


 f in d_ if ()

fi nd _i f( )
Find first match of a predicate in a sequence.

 f in d_ fi rs t_ of ()

fi nd _f ir st _o f( )
Find a value from one sequence in another.
 a dj ac en t_ fi nd ()

ad ja ce nt _f in d( )
Find an adjacent pair of values.


co un t( )
Count occurrences of a value in a sequence.
 c ou nt ()

co un t_ if ()
Count matches of a predicate in a sequence.
 c ou nt _i f( )

 m is ma tc h( )
mi sm at ch ()
Find the first elements for which two sequences differ.

 e qu al ()

eq ua l( )
True if the elements of two sequences are pairwise equal.
 s ea rc h( )


se ar ch ()
Find the first occurrence of a sequence as a subsequence.


fi nd _e nd ()
Find the last occurrence of a sequence as a subsequence.
 f in d_ en d( )

se ar ch _n ()
Find the n occurrence of a value in a sequence.
nth
 s ea rc h_ n( )
___________________________________________________________________
Most algorithms allow a user to specify the actual action performed for each element or pair of elements. This makes the algorithms much more general and useful than they appear at first glance.
In particular, a user can supply the criteria used for equality and difference (§18.4.2). Where reasonable, the most common and useful action is provided as a default.
Modifying sequence operations have little in common beyond the obvious fact that they might
change the values of elements of a sequence:
_
____________________________________________________________________

Modifying Sequence Operations (§18.6) <algorithm>
_
____________________________________________________________________
_
____________________________________________________________________


t ra ns fo rm ()
tr an sf or m( )

Apply an operation to every element in a sequence.


co py ()
Copy a sequence starting with its first element.
 c op y( )

co py _b ac kw ar d( )
Copy a sequence starting with its last element.
 c op y_ ba ck wa rd ()

 s wa p( )

sw ap ()
Swap two elements.
 i te r_ sw ap ()

it er _s wa p( )
Swap two elements pointed to by iterators.


sw ap _r an ge s( )
Swap elements of two sequences.
 s wa p_ ra ng es ()

re pl ac e( )
Replace elements with a given value.
 r ep la ce ()

re pl ac e_ if ()

Replace elements matching a predicate.
 r ep la ce _i f( )

 r ep la ce _c op y( )

re pl ac e_ co py ()
Copy sequence replacing elements with a given value.
 r ep la ce _c op y_ if ()

re pl ac e_ co py _i f( )
Copy sequence replacing elements matching a predicate.


fi ll ()
Replace every element with a given value.
 f il l( )

fi ll _n ()
Replace first n elements with a given value.
 f il l_ n( )

ge ne ra te ()
Replace every element with the result of an operation.
 g en er at e( )

 g en er at e_ n( )

ge ne ra te _n ()
Replace first n elements with the result of an operation.
 r em ov e( )


re mo ve ()
Remove elements with a given value.


Remove elements matching a predicate.
 re mo ve _i f( )
_r em ov e_ if ()
____________________________________________________________________

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


510

Algorithms and Function Objects

Chapter 18

_
_____________________________________________________________________
_____________________________________________________________________
Modifying Sequence Operations (continued) (§18.6) <algorithm>
_
_____________________________________________________________________
_


r em ov e_ co py ()

re mo ve _c op y( )
Copy a sequence removing elements with a given value.


re mo ve _c op y_ if ()
Copy a sequence removing elements matching a predicate.
 r em ov e_ co py _i f( )

 u ni qu e( )
un iq ue ()
Remove equal adjacent elements.

 u ni qu e_ co py ()

un iq ue _c op y( )
Copy a sequence removing equal adjacent elements.
 r ev er se ()

re ve rs e( )
Reverse the order of elements.


re ve rs e_ co py ()
Copy a sequence into reverse order.
 r ev er se _c op y( )

ro ta te ()
Rotate elements.
 r ot at e( )


 r ot at e_ co py ()
ro ta te _c op y( )
Copy a sequence into a rotated sequence.

_____________________________________________________________________
r an do m_ sh uf fl e( )
ra nd om _s hu ff le ()
Move elements into a uniform distribution.

_

Every good design shows traces of the personal traits and interests of its designer. The containers
and algorithms in the standard library clearly reflect a strong concern for classical data structures
and the design of algorithms. The standard library provides not only the bare minimum of containers and algorithms needed by essentially every programmer. It also includes many of the tools used
to provide those algorithms and needed to extend the library beyond that minimum.
The emphasis here is not on the design of algorithms or even on the use of any but the simplest
and most obvious algorithms. For information on the design and analysis of algorithms, you
should look elsewhere (for example, [Knuth,1968] and [Tarjan,1983]). Instead, this chapter lists
the algorithms offered by the standard library and explains how they are expressed in C++. This
focus allows someone who understands algorithms to use the library well and to extend it in the
spirit in which it was built.
The standard library provides a variety of operations for sorting, searching, and manipulating
sequences based on an ordering:
______________________________________________________________

Sorted Sequences (§18.7) <algorithm>
______________________________________________________________
______________________________________________________________



s or t( )
so rt ()
Sort with good average efficiency.


st ab le _s or t( )
Sort maintaining order of equal elements.
 s ta bl e_ so rt ()

pa rt ia l_ so rt ()
Get the first part of sequence into order.
 p ar ti al _s or t( )

 p ar ti al _s or t_ co py ()

pa rt ia l_ so rt _c op y( ) Copy getting the first part of output into order.
 n th _e le me nt ()

nt h_ el em en t( )
Put the nth element in its proper place.


lo we r_ bo un d( )
Find the first occurrence of a value.
 l ow er _b ou nd ()

up pe r_ bo un d( )
Find the first element larger than a value.
 u pp er _b ou nd ()


eq ua l_ ra ng e( )
Find a subsequence with a given value.
 e qu al _r an ge ()

 b in ar y_ se ar ch ()

bi na ry _s ea rc h( )
Is a given value in a sorted sequence?
 m er ge ()

me rg e( )
Merge two sorted sequences.


in pl ac e_ me rg e( )
Merge two consecutive sorted subsequences.
 i np la ce _m er ge ()

pa rt it io n( )
Place elements matching a predicate first.
 p ar ti ti on ()

 s ta bl e_ pa rt it io n( )
st ab le _p ar ti ti on ()
Place elements matching a predicate first,

_____________________________________________________________
preserving relative order.

_



The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 18.2

Overview of Standard Library Algorithms

511

_
____________________________________________________________________

Set Algorithms (§18.7.5) <algorithm>
_
____________________________________________________________________
_
____________________________________________________________________

in cl ud es ()
True if a sequence is a subsequence of another.
 i nc lu de s( )

se t_ un io n( )
Construct a sorted union.
 s et _u ni on ()

 s et _i nt er se ct io n( )

se t_ in te rs ec ti on ()
Construct a sorted intersection.

 s et _d if fe re nc e( )

se t_ di ff er en ce ()
Construct a sorted sequence of elements


in the first but not the second sequence.


se t_ sy mm et ri c_ di ff er en ce ()
Construct a sorted sequence of elements
 s et _s ym me tr ic _d if fe re nc e( )

in one but not both sequences.

_
____________________________________________________________________
Heap operations keep a sequence in a state that makes it easy to sort when necessary:
_____________________________________________________

Heap Operations (§18.8) <algorithm>
_____________________________________________________
_____________________________________________________

m ak e_ he ap ()
ma ke _h ea p( ) Make sequence ready to be used as a heap.



pu sh _h ea p( )
Add element to heap.
 p us h_ he ap ()

 p op _h ea p( )
po p_ he ap ()
Remove element from heap.

 s or t_ he ap ()
so rt _h ea p( )
Sort the heap.

_____________________________________________________

The library provides a few algorithms for selecting elements based on a comparison:
________________________________________________________________

Minimum and Maximum (§18.9) <algorithm>
________________________________________________________________
________________________________________________________________

mi n( )
Smaller of two values.

 m in ()
ma x( )
Larger of two values.

 m ax ()


 m in _e le me nt ()
mi n_ el em en t( )
Smallest value in sequence.

 m ax _e le me nt ()
ma x_ el em en t( )
Largest value in sequence.

 l ex ic og ra ph ic al _c om pa re ()
Lexicographically first of two sequences.
 le xi co gr ap hi ca l_ co mp ar e( )
________________________________________________________________
Finally, the library provides ways of permuting a sequence:
_
_____________________________________________________________
_____________________________________________________________
Permutations (§18.10) <algorithm>
_
_____________________________________________________________
_


ne xt _p er mu ta ti on ()
Next permutation in lexicographical order.
 n ex t_ pe rm ut at io n( )

pr ev _p er mu ta ti on ()
_____________________________________________________________
_p re v_ pe rm ut at io n( ) Previous permutation in lexicographical order.

In addition, a few generalized numerical algorithms are provided in nu me ri c>
In the description of algorithms, the template parameter names are significant. I n, O ut F or B i,
In Ou t, Fo r, Bi
and R an mean input iterator, output iterator, forward iterator, bidirectional iterator, and randomRa n
access iterator, respectively (§19.2.1). P re d means unary predicate, B in Pr ed means binary prediPr ed
Bi nP re d
cate (§18.4.2), C mp means a comparison function (§17.1.4.1, §18.7.1), O p means unary operation,
Cm p
Op
and B in Op means binary operation (§18.4). Conventionally, much longer names have been used
Bi nO p
for template parameters. However, I find that after only a brief acquaintance with the standard
library, those long names decrease readability rather than enhancing it.
A random-access iterator can be used as a bidirectional iterator, a bidirectional iterator as a forward iterator, and a forward iterator as an input or an output iterator (§19.2.1). Passing a type that
doesn’t provide the required operations will cause template-instantiation-time errors (§C.13.7).
Providing a type that has the right operations with the wrong semantics will cause unpredictable
run-time behavior (§17.1.4).

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


512

Algorithms and Function Objects

Chapter 18

18.3 Sequences and Containers [algo.seq]

It is a good general principle that the most common use of something should also be the shortest,
the easiest to express, and the safest. The standard library violates this principle in the name of
generality. For a standard library, generality is essential. For example, we can find the first two
occurrences of 4 2 in a list like this:
42
v oi d f li st in t>& l i)
vo id f(l is tli
{
l is tli st in t>: it er at or
fi nd li be gi n() li en d() 42
i f (p != l i.e nd
if p
li en d()) {
l is tli st in t>: it er at or
fi nd
p,l i.e nd
42
// ...
}
// ...
}

// first occurrence
// second occurrence

Had f in d() been expressed as an operation on a container, we would have needed some additional
fi nd

mechanism for finding the second occurrence. Importantly, generalizing such an ‘‘additional
mechanism’’ for every container and every algorithm is hard. Instead, standard library algorithms
work on sequences of elements. That is, the input of an algorithm is expressed as a pair of iterators
that delineate a sequence. The first iterator refers to the first element of the sequence, and the second refers to a point one-beyond-the-last element (§3.8, §19.2). Such a sequence is called ‘‘half
open’’ because it includes the first value mentioned and not the second. A half-open sequence
allows many algorithms to be expressed without making the empty sequence a special case.
A sequence – especially a sequence in which random access is possible – is often called a
range. Traditional mathematical notations for a half-open range are [f ir st la st and [f ir st la st
fi rs t,l as t)
fi rs t,l as t[.
Importantly, a sequence can be the elements of a container or a subsequence of a container. Further, some sequences, such as I/O streams, are not containers. However, algorithms expressed in
terms of sequences work just fine.
18.3.1 Input Sequences [algo.range]
Writing x be gi n(),x en d() to express ‘‘all the elements of x is common, tedious, and can even
x.b eg in
x.e nd
x’’
be error-prone. For example, when several iterators are used, it is too easy to provide an algorithm
with a pair of arguments that does not constitute a sequence:
v oi d f li st st ri ng
vo id f(l is t<s tr in g>& f ru it l is t<s tr in g>& c it ru s)
fr ui t, li st st ri ng
ci tr us
{
t yp ed ef l is t<s tr in g>::c on st _i te ra to r L I;
ty pe de f li st st ri ng
co ns t_ it er at or LI
L I p 1 = f in d(f ru it be gi n(),c it ru s.e nd ,"a pp le ;
LI p1 fi nd fr ui t.b eg in
ci tr us en d() ap pl e")

L I p 2 = f in d(f ru it be gi n(),f ru it en d(),"a pp le ;
LI p2 fi nd fr ui t.b eg in
fr ui t.e nd
ap pl e")
L I p 3 = f in d(c it ru s.b eg in ,c it ru s.e nd ,"p ea r");
LI p3 fi nd ci tr us be gi n() ci tr us en d() pe ar
L I p 4 = f in d(p 2,p 3,"p ea ch ;
LI p4 fi nd p2 p3 pe ac h")
// ...

// wrong! (different sequences)
// ok
// ok
// wrong! (different sequences)

}

In this example there are two errors. The first is obvious (once you suspect an error), but it isn’t

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 18.3.1

Input Sequences

513

easily detected by a compiler. The second is hard to spot in real code even for an experienced programmer. Cutting down on the number of explicit iterators used alleviates this problem. Here, I

outline an approach to dealing with this problem by making the notion of an input sequence
explicit. However, to keep the discussion of standard algorithms strictly within the bounds of the
standard library, I do not use explicit input sequences when presenting algorithms in this chapter.
The key idea is to be explicit about taking a sequence as input. For example:
t em pl at ete mp la te cl as s In cl as s T> In fi nd In fi rs t, In la st co ns t T& v)
{
w hi le (f ir st la st && *f ir st v) ++f ir st
wh il e fi rs t!=l as t
fi rs t!=v
fi rs t;
r et ur n f ir st
re tu rn fi rs t;
}

// standard

t em pl at ete mp la te cl as s In cl as s T> In fi nd Is eq In r, co ns t T& v)
{
r et ur n f in d(r fi rs t,r se co nd v);
re tu rn fi nd r.f ir st r.s ec on d,v
}

// extension

In general, overloading (§13.3.2) allows the input-sequence version of an algorithm to be preferred
when an I se q argument is used.
Is eq
Naturally, an input sequence is implemented as a pair (§17.4.1.2) of iterators:

t em pl at e<c la ss I n> s tr uc t I se q : p ub li c p ai r<I n,I n> {
te mp la te cl as s In st ru ct Is eq pu bl ic pa ir In In
I se q(I n i 1, I n i 2) : p ai r<I n,I n>(i 1,i 2) { }
Is eq In i1 In i2
pa ir In In i1 i2
};

We can explicitly make the I se q needed to invoke the second version of f in d():
Is eq
fi nd
L I p = f in d(I se q<L I>(f ru it be gi n(),f ru it en d()),"a pp le ;
LI
fi nd Is eq LI fr ui t.b eg in
fr ui t.e nd
ap pl e")

However, that is even more tedious than calling the original f in d() directly. Simple helper funcfi nd
tions relieve the tedium. In particular, the I se q of a container is the sequence of elements from its
Is eq
b eg in to its e nd
be gi n()
en d():
t em pl at ete mp la te cl as s C> Is eq C: it er at or _t yp e> is eq C& c)
{
r et ur n I se qre tu rn Is eq C: it er at or _t yp e>(c be gi n() c.e nd
}

// for container


This allows us to express algorithms on containers compactly and without repetition. For example:
v oi d f li st st ri ng
vo id f(l is t<s tr in g>& l s)
ls
{
l is t<s tr in g>::i te ra to r p = f in d(l s.b eg in ,l s.e nd ,"s ta nd ar d");
li st st ri ng
it er at or
fi nd ls be gi n() ls en d() st an da rd
l is t<s tr in g>::i te ra to r q = f in d (i se q(l s),"e xt en si on ;
li st st ri ng
it er at or
fi nd is eq ls
ex te ns io n")
// ..
}

It is easy to define versions of i se q() that produce I se qs for arrays, input streams, etc. (§18.13[6]).
is eq
Is eq
The key benefit of I se q is that it makes the notion of an input sequence explicit. The immediate
Is eq
practical effect is that use of i se q() eliminates much of the tedious and error-prone repetition
is eq
needed to express every input sequence as a pair of iterators.

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.



514

Algorithms and Function Objects

Chapter 18

The notion of an output sequence is also useful. However, it is less simple and less immediately useful than the notion of an input sequence (§18.13[7]; see also §19.2.4).

18.4 Function Objects [algo.fct]
Many algorithms operate on sequences using iterators and values only. For example, we can
f in d() the first element with the value 7 in a sequence like this:
fi nd
v oi d f li st in t>& c
vo id f(l is tc)
{
l is tli st in t>: it er at or
fi nd c.b eg in
c.e nd
7)
// ...
}

To do more interesting things we want the algorithms to execute code that we supply (§3.8.4). For
example, we can find the first element in a sequence with a value of less than 7 like this:
b oo l l es s_ th an _7 in t v
bo ol le ss _t ha n_ 7(i nt v)
{

r et ur n v 7;
re tu rn v<7
}
v oi d f li st in t>& c
vo id f(l is tc)
{
l is tli st in t>: it er at or
fi nd _i f(c be gi n() c.e nd
le ss _t ha n_ 7)
// ...
}

There are many obvious uses for functions passed as arguments: logical predicates, arithmetic operations, operations for extracting information from elements, etc. It is neither convenient nor efficient to write a separate function for each use. Nor is a function logically sufficient to express all
that we would like to express. Often, the function called for each element needs to keep data
between invocations and to return the result of many applications. A member function of a class
serves such needs better than a free-standing function does because its object can hold data. In
addition, the class can provide operations for initializing and extracting such data.
Consider how to write a function – or rather a function-like class – to calculate a sum:
t em pl at ete mp la te cl as s T> cl as s Su m
T r es
re s;
p ub li c:
pu bl ic
S um T i = 0 : r es i) { }
Su m(T
0) re s(i
// initialize

v oi d o pe ra to r()(T x { r es += x }
vo id op er at or
T x) re s
x;
// accumulate
T r es ul t() c on st { r et ur n r es }
re su lt
co ns t re tu rn re s;
// return sum
};

Clearly, S um is designed for arithmetic types for which initialization by 0 and += are defined. For
Su m
example:

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 18.4

v oi d f li st do ub le
vo id f(l is t<d ou bl e>& l d)
ld
{
S um do ub le s
Su m<d ou bl e> s;
s = f or _e ac h(l d.b eg in ,l d.e nd ,s ;
fo r_ ea ch ld be gi n() ld en d() s)
c ou t << "t he s um i s" << s re su lt

co ut
th e su m is
s.r es ul t() << ´\ n´;
\n
}

Function Objects

515

// invoke s() for each element of ld

Here, f or _e ac h() (§18.5.1) invokes S um do ub le :o pe ra to r()(d ou bl e) for each element of l d
fo r_ ea ch
Su m<d ou bl e>: op er at or
do ub le
ld
and returns the object passed as its third argument.
The key reason this works is that f or _e ac h() doesn’t actually assume its third argument to be a
fo r_ ea ch
function. It simply assumes that its third argument is something that can be called with an appropriate argument. A suitably-defined object serves as well as – and often better than – a function.
For example, it is easier to inline the application operator of a class than to inline a function passed
as a pointer to function. Consequently, function objects often execute faster than do ordinary functions. An object of a class with an application operator (§11.9) is called a function-like object, a
functor, or simply a function object.
18.4.1 Function Object Bases [algo.bases]
The standard library provides many useful function objects. To aid the writing of function objects,
the library provides a couple of base classes:
t em pl at e te mp la te cl as s Ar g, cl as s Re s> st ru ct un ar y_ fu nc ti on
t yp ed ef A rg a rg um en t_ ty pe

ty pe de f Ar g ar gu me nt _t yp e;
t yp ed ef R es r es ul t_ ty pe
ty pe de f Re s re su lt _t yp e;
};
t em pl at e te mp la te cl as s Ar g, cl as s Ar g2 cl as s Re s> st ru ct bi na ry _f un ct io n
t yp ed ef A rg f ir st _a rg um en t_ ty pe
ty pe de f Ar g fi rs t_ ar gu me nt _t yp e;
t yp ed ef A rg 2 s ec on d_ ar gu me nt _t yp e;
ty pe de f Ar g2 se co nd _a rg um en t_ ty pe
t yp ed ef R es r es ul t_ ty pe
ty pe de f Re s re su lt _t yp e;
};

The purpose of these classes is to provide standard names for the argument and return types for use
by users of classes derived from u na ry _f un ct io n and b in ar y_ fu nc ti on Using these bases consisun ar y_ fu nc ti on
bi na ry _f un ct io n.
tently the way the standard library does will save the programmer from discovering the hard way
why they are useful (§18.4.4.1).
18.4.2 Predicates [algo.pred]
A predicate is a function object (or a function) that returns a b oo l. For example, <f un ct io na l>
bo ol
fu nc ti on al
defines:
t em pl at e te mp la te cl as s T> st ru ct lo gi ca l_ no t pu bl ic un ar y_ fu nc ti on T,b oo l>
b oo l o pe ra to r()(c on st T x c on st { r et ur n !x }
bo ol op er at or
co ns t T& x) co ns t re tu rn x;
};

t em pl at e te mp la te cl as s T> st ru ct le ss pu bl ic bi na ry _f un ct io n<T T,b oo l>
b oo l o pe ra to r()(c on st T x c on st T y c on st { r et ur n x y; }
bo ol op er at or
co ns t T& x, co ns t T& y) co ns t re tu rn x};

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


516

Algorithms and Function Objects

Chapter 18

Unary and binary predicates are often useful in combination with algorithms. For example, we can
compare two sequences, looking for the first element of one that is not less than its corresponding
element in the other:
v oi d f ve ct or in t>& v i, l is tvo id f(v ec to rvi li st in t>& li
{
t yp ed ef l is tty pe de f li st in t>: it er at or LI
t yp ed ef v ec to rty pe de f ve ct or in t>: it er at or VI
p ai r<V I,L I> p 1 = m is ma tc h(v i.b eg in ,v i.e nd ,l i.b eg in ,l es spa ir VI LI p1 mi sm at ch vi be gi n() vi en d() li be gi n() le ss in t>());

// ...
}

The m is ma tc h() algorithm applies its binary predicate repeatedly to pairs of corresponding elemi sm at ch
ments until it fails (§18.5.4). It then returns the iterators for the elements that failed the comparison. Because an object is needed rather than a type, l es sle ss in t>() (with the parentheses) is used
rather than the tempting l es sle ss in t>.
Instead of finding the first element n ot l es s than its corresponding element in the other
no t le ss
sequence, we might like to find the first element l es s than its corresponding element. We can do
le ss
this by presenting the sequences to m is ma tc h() in the opposite order:
mi sm at ch
p ai r<L I,V I> p 2 = m is ma tc h(l i.b eg in ,l i.e nd ,v i.b eg in ,l es spa ir LI VI p2 mi sm at ch li be gi n() li en d() vi be gi n() le ss in t>());

or we can use the complementary predicate g re at er _e qu al
gr ea te r_ eq ua l:
p 1 = m is ma tc h(v i.b eg in ,v i.e nd ,l i.b eg in ,g re at er _e qu al in t>());
p1 mi sm at ch vi be gi n() vi en d() li be gi n() gr ea te r_ eq ua l
In §18.4.4.4, I show how to express the predicate ‘‘not less.’’
18.4.2.1 Overview of Predicates [algo.pred.std]
In <f un ct io na l>, the standard library supplies a few common predicates:
fu nc ti on al
_
______________________________________
______________________________________
Predicates <functional>

_
_
______________________________________
e qu al _t o
eq ua l_ to
Binary arg1==arg2


n ot _e qu al _t o
no t_ eq ua l_ to
Binary arg1!=arg2


 g re at er
gr ea te r
Binary arg1>arg2

 l es s

le ss
Binary arg1 g re at er _e qu al

gr ea te r_ eq ua l
Binary arg1>=arg2


le ss _e qu al
Binary arg1<=arg2
 l es s_ eq ua l


lo gi ca l_ an d
Binary arg1&&arg2
 l og ic al _a nd

 l og ic al _o r
lo gi ca l_ or
Binary arg1arg2

______________________________________
l og ic al _n ot
lo gi ca l_ no t
Unary
!arg

_

The definitions of l es s and l og ic al _n ot are presented in §18.4.2.
le ss
lo gi ca l_ no t
In addition to the library-provided predicates, users can write their own. Such user-supplied
predicates are essential for simple and elegant use of the standard libraries and algorithms. The
ability to define predicates is particularly important when we want to use algorithms for classes
designed without thought of the standard library and its algorithms. For example, consider a variant of the C lu b class from §10.4.6:
Cl ub

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.



Section 18.4.2.1

Overview of Predicates

517

c la ss P er so n { /* ... */ };
cl as s Pe rs on
s tr uc t C lu b {
st ru ct Cl ub
s tr in g n am e;
st ri ng na me
l is t<P er so n*> m em be rs
li st Pe rs on
me mb er s;
l is t<P er so n*> o ff ic er s;
li st Pe rs on
of fi ce rs
// ...
C lu b(c on st n am e& n ;
Cl ub co ns t na me n)
};

Looking for a C lu b with a given name in a l is t<C lu b> is clearly a reasonable thing to do. HowCl ub
li st Cl ub
ever, the standard library algorithm f in d_ if
fi nd _i f() doesn’t know about C lu bs. The library algorithms
Cl ub
know how to test for equality, but we don’t want to find a C lu b based on its complete value.
Cl ub

Rather, we want to use C lu b::n am e as the key. So we write a predicate to reflect that:
Cl ub na me
c la ss C lu b_ eq : p ub li c u na ry _f un ct io n<C lu b,b oo l> {
cl as s Cl ub _e q pu bl ic un ar y_ fu nc ti on Cl ub bo ol
s tr in g s
st ri ng s;
p ub li c:
pu bl ic
e xp li ci t C lu b_ eq co ns t s tr in g& s s) : s ss { }
ex pl ic it Cl ub _e q(c on st st ri ng ss
s(s s)
b oo l o pe ra to r()(c on st C lu b& c c on st { r et ur n c na me s; }
bo ol op er at or
co ns t Cl ub c) co ns t re tu rn c.n am e==s
};

Defining useful predicates is simple. Once suitable predicates have been defined for user-defined
types, their use with the standard algorithms is as simple and efficient as examples involving containers of simple types. For example:
v oi d f li st Cl ub
vo id f(l is t<C lu b>& l c)
lc
{
t yp ed ef l is t<C lu b>::i te ra to r L CI
ty pe de f li st Cl ub
it er at or LC I;
L CI p = f in d_ if lc be gi n(),l c.e nd ,C lu b_ eq Di ni ng P hi lo so ph er s"));
LC I
fi nd _i f(l c.b eg in
lc en d() Cl ub _e q("D in in g Ph il os op he rs
// ...

}

18.4.3 Arithmetic Function Objects [algo.arithmetic]
When dealing with numeric classes, it is sometimes useful to have the standard arithmetic functions
available as function objects. Consequently, in <f un ct io na l> the standard library provides:
fu nc ti on al
_
_________________________________
_________________________________
_ Arithmetic Operations <functional> 
_
_________________________________
pl us
Binary arg1+arg2
 p lu s

m in us
mi nu s
Binary arg1– arg2


 m ul ti pl ie s
mu lt ip li es
Binary arg1*arg2

 d iv id es

di vi de s
Binary arg1/arg2
 m od ul us


mo du lu s
Binary arg1%arg2


ne ga te
Unary
– arg
_________________________________
_n eg at e
We might use m ul ti pl ie s to multiply elements in two vectors, thereby producing a third:
mu lt ip li es

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


518

Algorithms and Function Objects

Chapter 18

v oi d d is co un t(v ec to r<d ou bl e>& a v ec to r<d ou bl e>& b v ec to r<d ou bl e>& r es
vo id di sc ou nt ve ct or do ub le
a, ve ct or do ub le
b, ve ct or do ub le
re s)
{
t ra ns fo rm a.b eg in ,a en d(),b be gi n(),b ac k_ in se rt er re s),m ul ti pl ie s<d ou bl e>());

tr an sf or m(a be gi n() a.e nd
b.b eg in
ba ck _i ns er te r(r es mu lt ip li es do ub le
}

The b ac k_ in se rt er is described in §19.2.4. A few numerical algorithms can be found in §22.6.
ba ck _i ns er te r()
18.4.4 Binders, Adapters, and Negaters [algo.adapter]
We can use predicates and arithmetic function objects we have written ourselves and rely on the
ones provided by the standard library. However, when we need a new predicate we often find that
the new predicate is a minor variation of an existing one. The standard library supports the composition of function objects:
§18.4.4.1 A binder allows a two-argument function object to be used as a single-argument
function by binding one argument to a value.
§18.4.4.2 A member function adapter allows a member function to be used as an argument to
algorithms.
§18.4.4.3 A pointer to function adapter allows a pointer to function to be used as an argument
to algorithms.
§18.4.4.4 A negater allows us to express the opposite of a predicate.
Collectively, these function objects are referred to as a da pt er s. These adapters all have a common
ad ap te rs
structure relying on the function object bases u na ry _f un ct io n and b in ar y_ fu nc ti on (§18.4.1). For
un ar y_ fu nc ti on
bi na ry _f un ct io n
each of these adapters, a helper function is provided to take a function object as an argument and
return a suitable function object. When invoked by its o pe ra to r()(), that function object will
op er at or
perform the desired action. That is, an adapter is a simple form of a higher-order function: it takes
a function argument and produces a new function from it:
_
_______________________________________________________________________________


Binders, Adapters, and Negaters <functional>
_
_______________________________________________________________________________
_
_______________________________________________________________________________


binder2nd
Call binary function with y as 2nd argument. 
 bind2nd(y)
bi nd 1s t( x)
b in de r1 st
bi nd er 1s t
Call binary function with x as 1st argument. 
 b in d1 st (x )
me m_ fu n( )
m em _f un _t
me m_ fu n_ t
Call 0-arg member through pointer.
 m em _f un ()



m em _f un 1_ t
me m_ fu n1 _t
Call unary member through pointer.


c on st _m em _f un _t

co ns t_ me m_ fu n_ t
Call 0-arg const member through pointer.


c on st _m em _f un 1_ t
co ns t_ me m_ fu n1 _t
Call unary const member through pointer.


me m_ fu n_ re f( ) m em _f un _r ef _t
me m_ fu n_ re f_ t
Call 0-arg member through reference.
 m em _f un _r ef ()

m em _f un 1_ re f_ t
me m_ fu n1 _r ef _t
Call unary member through reference.



c on st _m em _f un _r ef _t
co ns t_ me m_ fu n_ re f_ t
Call 0-arg const member through reference. 

c on st _m em _f un 1_ re f_ t
co ns t_ me m_ fu n1 _r ef _t
Call unary const member through reference. 


pt r_ fu n( )

p oi nt er _t o_ un ar y_ fu nc ti on
po in te r_ to _u na ry _f un ct io n
Call unary pointer to function.
 p tr _f un ()

pt r_ fu n( )
p oi nt er _t o_ bi na ry _f un ct io n
po in te r_ to _b in ar y_ fu nc ti on
Call binary pointer to function.
 p tr _f un ()

no t1 ()
u na ry _n eg at e
un ar y_ ne ga te
Negate unary predicate.
 n ot 1( )

 n ot 2( )
b in ar y_ ne ga te
bi na ry _n eg at e
Negate binary predicate.

_no t2 ()
_______________________________________________________________________________


The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.



Section 18.4.4.1

Binders

519

18.4.4.1 Binders [algo.binder]
Binary predicates such as l es s (§18.4.2) are useful and flexible. However, we soon discover that
le ss
the most useful kind of predicate is one that compares a fixed argument repeatedly against a container element. The l es s_ th an _7
le ss _t ha n_ 7() function (§18.4) is a typical example. The l es s operation
le ss
needs two arguments explicitly provided in each call, so it is not immediately useful. Instead, we
might define:
t em pl at e te mp la te cl as s T> cl as s le ss _t ha n pu bl ic un ar y_ fu nc ti on T,b oo l>
T a rg 2;
ar g2
p ub li c:
pu bl ic
e xp li ci t l es s_ th an co ns t T x : a rg 2(x { }
ex pl ic it le ss _t ha n(c on st T& x) ar g2 x)
b oo l o pe ra to r()(c on st T x c on st { r et ur n x ar g2 }
bo ol op er at or
co ns t T& x) co ns t re tu rn x
};

We can now write:
v oi d f li st in t>& c
vo id f(l is t

c)
{
l is t<i nt :c on st _i te ra to r p = f in d_ if c.b eg in ,c en d(),l es s_ th an in t>(7 ;
li st in t>: co ns t_ it er at or
fi nd _i f(c be gi n() c.e nd
le ss _t ha n// ...
}

We must write l es s_ th an in t>(7 rather than l es s_ th an 7) because the template argument le ss _t ha nle ss _t ha n(7
in t>
cannot be deduced from the type of the constructor argument (7 (§13.3.1).
7)
The l es s_ th an predicate is generally useful. Importantly, we defined it by fixing or binding the
le ss _t ha n
second argument of l es s. Such composition by binding an argument is so common, useful, and
le ss
occasionally tedious that the standard library provides a standard class for doing it:
t em pl at e te mp la te cl as s Bi nO p>
c la ss b in de r2 nd : p ub li c u na ry _f un ct io ncl as s bi nd er 2n d pu bl ic un ar y_ fu nc ti on Bi nO p: fi rs t_ ar gu me nt _t yp e, Bi nO p: re su lt _t yp e>
p ro te ct ed
pr ot ec te d:
B in Op o p;
Bi nO p op
t yp en am e B in Op :s ec on d_ ar gu me nt _t yp e a rg 2;
ty pe na me Bi nO p: se co nd _a rg um en t_ ty pe ar g2

p ub li c:
pu bl ic
b in de r2 nd co ns t B in Op x c on st t yp en am e B in Op :s ec on d_ ar gu me nt _t yp e& v
bi nd er 2n d(c on st Bi nO p& x, co ns t ty pe na me Bi nO p: se co nd _a rg um en t_ ty pe v)
: o p(x , a rg 2(v { }
op x) ar g2 v)
r es ul t_ ty pe o pe ra to r()(c on st a rg um en t_ ty pe x c on st { r et ur n o p(x ar g2 ; }
re su lt _t yp e op er at or
co ns t ar gu me nt _t yp e& x) co ns t re tu rn op x,a rg 2)
};
t em pl at e <c la ss B in Op c la ss T b in de r2 nd Bi nO p> b in d2 nd co ns t B in Op o p, c on st T v
te mp la te cl as s Bi nO p, cl as s T> bi nd er 2n d{
r et ur n b in de r2 nd Bi nO p>(o p,v ;
re tu rn bi nd er 2n d}

For example, we can use b in d2 nd
bi nd 2n d() to create the unary predicate ‘‘less than 7 from the binary
7’’
predicate ‘‘less’’ and the value 7
7:

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


520

Algorithms and Function Objects


Chapter 18

v oi d f li st in t>& c
vo id f(l is tc)
{
l is t<i nt :c on st _i te ra to r p = f in d_ if c.b eg in ,c en d(),b in d2 nd le ss in t>(),7 ;
li st in t>: co ns t_ it er at or
fi nd _i f(c be gi n() c.e nd
bi nd 2n d(l es s7))
// ...
}

Is this readable? Is this efficient? Given an average C++ implementation, this version is actually
more efficient in time and space than is the original version using the function l es s_ th an _7 from
le ss _t ha n_ 7()
§18.4! The comparison is easily inlined.
The notation is logical, but it does take some getting used to. Often, the definition of a named
operation with a bound argument is worthwhile after all:
t em pl at e <c la ss T s tr uc t l es s_ th an : p ub li c b in de r2 nd le ss T>,T {
te mp la te cl as s T> st ru ct le ss _t ha n pu bl ic bi nd er 2n de xp li ci t l es s_ th an co ns t T x : b in de r2 nd le ss T>(),x { }
ex pl ic it le ss _t ha n(c on st T& x) bi nd er 2n d(l es sx)
};
v oi d f li st in t>& c
vo id f(l is tc)

{
l is t<i nt :c on st _i te ra to r p = f in d_ if c.b eg in ,c en d(),l es s_ th an in t>(7 ;
li st in t>: co ns t_ it er at or
fi nd _i f(c be gi n() c.e nd
le ss _t ha n// ...
}

It is important to define l es s_ th an in terms of l es s rather than using < directly. That way,
le ss _t ha n
le ss
l es s_ th an benefits from any specializations that l es s might have (§13.5, §19.2.2).
le ss _t ha n
le ss
In parallel to b in d2 nd
bi nd 2n d() and b in de r2 nd <f un ct io na l> provides b in d1 st
bi nd er 2n d, fu nc ti on al
bi nd 1s t() and b in de r1 st for
bi nd er 1s t
binding the first argument of a binary function.
By binding an argument, b in d1 st
bi nd 1s t() and b in d2 nd
bi nd 2n d() perform a service very similar to what is
commonly referred to as Currying.
18.4.4.2 Member Function Adapters [algo.memfct]
Most algorithms invoke a standard or user-defined operation. Naturally, users often want to invoke
a member function. For example (§3.8.5):
v oi d d ra w_ al l(l is tvo id dr aw _a ll li st Sh ap e*>& l sp
ls p)

{
f or _e ac h(c be gi n(),c en d(),&S ha pe :d ra w); // oops! error
fo r_ ea ch c.b eg in
c.e nd
Sh ap e: dr aw
}

The problem is that a member function m f() needs to be invoked for an object: p mf
mf
p->m f(). However, algorithms such as f or _e ac h() invoke their function operands by simple application: f
fo r_ ea ch
f().
Consequently, we need a convenient and efficient way of creating something that allows an algorithm to invoke a member function. The alternative would be to duplicate the set of algorithms:
one version for member functions plus one for ordinary functions. Worse, we’d need additional
versions of algorithms for containers of objects (rather than pointers to objects). As for the binders
(§18.4.4.1), this problem is solved by a class plus a function. First, consider the common case in
which we want to call a member function taking no arguments for the elements of a container of
pointers:

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 18.4.4.2

Member Function Adapters

521

t em pl at e

te mp la te cl as s R, cl as s T> cl as s me m_ fu n_ t pu bl ic un ar y_ fu nc ti on T*,R
R (T :*p mf
T: pm f)();
p ub li c:
pu bl ic
e xp li ci t m em _f un _t R (T :*p
ex pl ic it me m_ fu n_ t(R T: p)()) :p mf p) {}
pm f(p
R o pe ra to r()(T p c on st { r et ur n (p
op er at or
T* p) co ns t re tu rn p->*p mf
pm f)(); } // call through pointer
};
t em pl at ete mp la te cl as s R, cl as s T> me m_ fu n_ t<R T> me m_ fu n(R T: f)())
{
r et ur n m em _f un _t R,T f);
re tu rn me m_ fu n_ t<R T>(f
}

This handles the S ha pe :d ra w() example:
Sh ap e: dr aw
v oi d d ra w_ al l(l is tvo id dr aw _a ll li st Sh ap e*>& l sp
ls p)
// call 0-argument member through pointer to object
{
f or _e ac h(l sp be gi n(),l sp en d(),m em _f un Sh ap e::d ra w)); // draw all shapes
fo r_ ea ch ls p.b eg in
ls p.e nd

me m_ fu n(&S ha pe dr aw
}

In addition, we need a class and a m em _f un
me m_ fu n() function for handling a member function taking an
argument. We also need versions to be called directly for an object rather than through a pointer;
these are named m em _f un _r ef
me m_ fu n_ re f(). Finally, we need versions for c on st member functions:
co ns t
t em pl at ete mp la te cl as s R, cl as s T> me m_ fu n_ t<R T> me m_ fu n(R T: f)());
// and versions for unary member, for const member, and const unary member (see table in §18.4.4)
t em pl at ete mp la te cl as s R, cl as s T> me m_ fu n_ re f_ t<R T> me m_ fu n_ re f(R T: f)());
// and versions for unary member, for const member, and const unary member (see table in §18.4.4)

Given these member function adapters from <f un ct io na l>, we can write:
fu nc ti on al
v oi d f li st st ri ng
vo id f(l is t<s tr in g>& l s)
ls
// use member function that takes no argument for object
{
t yp ed ef l is t<s tr in g>::i te ra to r L SI
ty pe de f li st st ri ng
it er at or LS I;
L SI p = f in d_ if ls be gi n(),l s.e nd ,m em _f un _r ef st ri ng :e mp ty ;// find ""
LS I
fi nd _i f(l s.b eg in
ls en d() me m_ fu n_ re f(&s tr in g: em pt y))

}
v oi d r ot at e_ al l(l is tvo id ro ta te _a ll li st Sh ap e*>& l s, i nt a ng le
ls in t an gl e)
// use member function that takes one argument through pointer to object
{
f or _e ac h(l s.b eg in ,l s.e nd ,b in d2 nd me m_ fu n(&S ha pe :r ot at e),a ng le ;
fo r_ ea ch ls be gi n() ls en d() bi nd 2n d(m em _f un Sh ap e: ro ta te an gl e))
}

The standard library need not deal with member functions taking more than one argument because
no standard library algorithm takes a function with more than two arguments as operands.
18.4.4.3 Pointer to Function Adapters [algo.ptof]
An algorithm doesn’t care whether a ‘‘function argument’’ is a function, a pointer to function, or a
function object. However, a binder (§18.4.4.1) does care because it needs to store a copy for later
use. Consequently, the standard library supplies two adapters to allow pointers to functions to be
used together with the standard algorithms in <f un ct io na l>. The definition and implementation
fu nc ti on al

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


522

Algorithms and Function Objects

Chapter 18

closely follows that of the member function adapters (§18.4.4.2). Again, a pair of functions and a

pair of classes are used:
t em pl at e te mp la te cl as s A, cl as s R> po in te r_ to _u na ry _f un ct io n<A R> pt r_ fu n(R
f)(A
t em pl at e te mp la te cl as s A, cl as s A2 cl as s R>
p oi nt er _t o_ bi na ry _f un ct io n<A A2 R> p tr _f un R (*f A, A 2));
po in te r_ to _b in ar y_ fu nc ti on A,A 2,R pt r_ fu n(R
f)(A A2

Given these pointer to function adapters, we can use ordinary functions together with binders:
c la ss R ec or d { /* ... */ };
cl as s Re co rd
b oo l n am e_ ke y_ eq co ns t R ec or d&, c on st R ec or d&); // compare based on names
bo ol na me _k ey _e q(c on st Re co rd
co ns t Re co rd
b oo l s sn _k ey _e q(c on st R ec or d&, c on st R ec or d&); // compare based on number
bo ol ss n_ ke y_ eq co ns t Re co rd
co ns t Re co rd
v oi d f li st Re co rd
vo id f(l is t<R ec or d>& l r) // use pointer to function
lr
{
t yp ed ef t yp en am e l is t<R ec or d>::i te ra to r L I;
ty pe de f ty pe na me li st Re co rd
it er at or LI
L I p = f in d_ if lr be gi n(),l r.e nd ,b in d2 nd pt r_ fu n(n am e_ ke y_ eq ,"J oh n B ro wn
LI
fi nd _i f(l r.b eg in
lr en d() bi nd 2n d(p tr _f un na me _k ey _e q) Jo hn Br ow n"));

L I q = f in d_ if lr be gi n(),l r.e nd ,b in d2 nd pt r_ fu n(s sn _k ey _e q),1 23 45 67 89 0));
LI
fi nd _i f(l r.b eg in
lr en d() bi nd 2n d(p tr _f un ss n_ ke y_ eq 12 34 56 78 90
// ...
}

This looks for elements of the list l r that match the keys J oh n B ro wn and 1 23 45 67 89 0.
lr
Jo hn Br ow n
12 34 56 78 90
18.4.4.4 Negaters [algo.negate]
The predicate negaters are related to the binders in that they take an operation and produce a related
operation from it. The definition and implementation of negaters follow the pattern of the member
function adapters (§18.4.4.2). Their definitions are trivial, but their simplicity is obscured by the
use of long standard names:
t em pl at e <c la ss P re d>
te mp la te cl as s Pr ed
c la ss u na ry _n eg at e : p ub li c u na ry _f un ct io ncl as s un ar y_ ne ga te pu bl ic un ar y_ fu nc ti on ty pe na me Pr ed ar gu me nt _t yp e,b oo l>
u na ry _f un ct io n
un ar y_ fu nc ti on ar gu me nt _t yp e,b oo l> op
p ub li c:
pu bl ic
e xp li ci t u na ry _n eg at e(c on st P re d& p : o p(p { }
ex pl ic it un ar y_ ne ga te co ns t Pr ed p) op p)
b oo l o pe ra to r()(c on st a rg um en t_ ty pe x c on st { r et ur n !o p(x ; }
bo ol op er at or
co ns t ar gu me nt _t yp e& x) co ns t re tu rn op x)
};

t em pl at e <c la ss P re d>
te mp la te cl as s Pr ed
c la ss b in ar y_ ne ga te : p ub li c b in ar y_ fu nc ti on ty pe na me P re d::f ir st _a rg um en t_ ty pe
cl as s bi na ry _n eg at e pu bl ic bi na ry _f un ct io nt yp en am e P re d::s ec on d_ ar gu me nt _t yp e, b oo l> {
ty pe na me Pr ed se co nd _a rg um en t_ ty pe bo ol
t yp ed ef f ir st _a rg um en t_ ty pe A rg
ty pe de f fi rs t_ ar gu me nt _t yp e Ar g;
t yp ed ef s ec on d_ ar gu me nt _t yp e A rg 2;
ty pe de f se co nd _a rg um en t_ ty pe Ar g2
b in ar y_ fu nc ti on Ar g, A rg 2, b oo l> o p;
bi na ry _f un ct io n
p ub li c:
pu bl ic
e xp li ci t b in ar y_ ne ga te co ns t P re d& p : o p(p { }
ex pl ic it bi na ry _n eg at e(c on st Pr ed p) op p)
b oo l o pe ra to r()(c on st A rg x c on st A rg 2& y c on st { r et ur n !o p(x y); }
bo ol op er at or
co ns t Ar g& x, co ns t Ar g2 y) co ns t re tu rn op x,y
};

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


Section 18.4.4.4

Negaters

t em pl at e<c la ss P re d> u na ry _n eg at e<P re d> n ot 1(c on st P re d& p ;

te mp la te cl as s Pr ed un ar y_ ne ga te Pr ed no t1 co ns t Pr ed p)
t em pl at e<c la ss P re d> b in ar y_ ne ga te Pr ed n ot 2(c on st P re d& p ;
te mp la te cl as s Pr ed bi na ry _n eg at e<P re d> no t2 co ns t Pr ed p)

523

// negate unary
// negate binary

These classes and functions are declared in <f un ct io na l>. The names f ir st _a rg um en t_ ty pe
fu nc ti on al
fi rs t_ ar gu me nt _t yp e,
s ec on d_ ar gu me nt _t yp e, etc., come from the standard base classes u na ry _f un ct io n and
se co nd _a rg um en t_ ty pe
un ar y_ fu nc ti on
b in ar y_ fu nc ti on
bi na ry _f un ct io n.
Like the binders, the negaters are most conveniently used indirectly through their helper functions. For example, we can express the binary predicate ‘‘not less than’’ and use it to find the first
corresponding pair of elements whose first element is greater than or equal to its second:
v oi d f ve ct or in t>& v i, l is tvo id f(v ec to rvi li st in t>& li
{
// ...
p 1 = m is ma tc h(v i.b eg in ,v i.e nd ,l i.b eg in ,n ot 2(l es sp1 mi sm at ch vi be gi n() vi en d() li be gi n() no t2 le ss in t>()));
// ...
}

That is, p 1 identifies the first pair of elements for which the predicate n ot l es s t ha n failed.

p1
no t le ss th an
Predicates deal with Boolean conditions, so there are no equivalents to the bitwise operators |,
&, ^, and ~.
Naturally, binders, adapters, and negaters are useful in combination. For example:
e xt er n "C i nt s tr cm p(c on st c ha r*,c on st c ha r*);
ex te rn C" in t st rc mp co ns t ch ar co ns t ch ar

// from <cstdlib>

v oi d f li st ch ar
vo id f(l is t<c ha r*>& l s)
ls
// use pointer to function
{
t yp ed ef t yp en am e l is t<c ha r*>::c on st _i te ra to r L I;
ty pe de f ty pe na me li st ch ar
co ns t_ it er at or LI
L I p = f in d_ if ls be gi n(),l s.e nd ,n ot 1(b in d2 nd pt r_ fu n(s tr cm p),"f un ny
LI
fi nd _i f(l s.b eg in
ls en d() no t1 bi nd 2n d(p tr _f un st rc mp
fu nn y")));
}

This finds an element of the list l s that contains the C-style string "f un ny The negater is needed
ls
fu nn y".
because s tr cm p() returns 0 when strings compare equal.
st rc mp


18.5 Nonmodifying Sequence Algorithms [algo.nonmodifying]
Nonmodifying sequence algorithms are the basic means for finding something in a sequence without writing a loop. In addition, they allow us to find out things about elements. These algorithms
can take const-iterators (§19.2.1) and – with the excetion of f or _e ac h() – should not be used to
fo r_ ea ch
invoke operations that modify the elements of the sequence.
18.5.1 For_each [algo.foreach]
We use a library to benefit from the work of others. Using a library function, class, algorithm, etc.,
saves the work of inventing, designing, writing, debugging, and documenting something. Using
the standard library also makes the resulting code easier to read for others who are familiar with
that library, but who would have to spend time and effort understanding home-brewed code.
A key benefit of the standard library algorithms is that they save the programmer from writing
explicit loops. Loops can be tedious and error-prone. The f or _e ac h() algorithm is the simplest
fo r_ ea ch

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.


524

Algorithms and Function Objects

Chapter 18

algorithm in the sense that it does nothing but eliminate an explicit loop. It simply calls its operator
argument for a sequence:
t em pl at e<c la ss I n, c la ss O p> O p f or _e ac h(I n f ir st I n l as t, O p f
te mp la te cl as s In cl as s Op Op fo r_ ea ch In fi rs t, In la st Op f)
{

w hi le (f ir st != l as t) f fi rs t++);
wh il e fi rs t
la st f(*f ir st
r et ur n f
re tu rn f;
}

What functions would people want to call this way? If you want to accumulate information from
the elements, consider a cc um ul at e() (§22.6). If you want to find something in a sequence, conac cu mu la te
sider f in d() and f in d_ if
fi nd
fi nd _i f() (§18.5.2). If you change or remove elements, consider r ep la ce
re pl ac e()
(§18.6.4) or r em ov e() (§18.6.5). In general, before using f or _e ac h(), consider if there is a more
re mo ve
fo r_ ea ch
specialized algorithm that would do more for you.
The result of f or _e ac h() is the function or function object passed as its third argument. As
fo r_ ea ch
shown in the S um example (§18.4), this allows information to be passed back to a caller.
Su m
One common use of f or _e ac h() is to extract information from elements of a sequence. For
fo r_ ea ch
example, consider collecting the names of any of a number of C lu bs:
Cl ub
v oi d e xt ra ct co ns t l is t<C lu b>& l c, l is t<P er so n*>& o ff // place the officers from ‘lc’ on ‘off’
vo id ex tr ac t(c on st li st Cl ub
lc li st Pe rs on
of f)
{

f or _e ac h(l c.b eg in ,l c.e nd ,E xt ra ct _o ff ic er s(o ff ;
fo r_ ea ch lc be gi n() lc en d() Ex tr ac t_ of fi ce rs of f))
}

In parallel to the examples from §18.4 and §18.4.2, we define a function class that extracts the
desired information. In this case, the names to be extracted are found in l is t<P er so n*>s in our
li st Pe rs on
l is t<C lu b>. Consequently, E xt ra ct _o ff ic er s needs to copy the officers from a C lu b’s o ff ic er s list
li st Cl ub
Ex tr ac t_ of fi ce rs
Cl ub of fi ce rs
to our list:
c la ss E xt ra ct _o ff ic er s {
cl as s Ex tr ac t_ of fi ce rs
l is t<P er so n*>& l st
li st Pe rs on
ls t;
p ub li c:
pu bl ic
e xp li ci t E xt ra ct _o ff ic er s(l is t<P er so n*>& x : l st x) { }
ex pl ic it Ex tr ac t_ of fi ce rs li st Pe rs on
x) ls t(x
v oi d o pe ra to r()(c on st C lu b& c
vo id op er at or
co ns t Cl ub c)
{ c op y(c of fi ce rs be gi n(),c of fi ce rs en d(),b ac k_ in se rt er ls t)); }
co py c.o ff ic er s.b eg in
c.o ff ic er s.e nd
ba ck _i ns er te r(l st
};


We can now print out the names, again using f or _e ac h():
fo r_ ea ch
v oi d e xt ra ct _a nd _p ri nt co ns t l is t<C lu b>& l c)
vo id ex tr ac t_ an d_ pr in t(c on st li st Cl ub
lc
{
l is t<P er so n*> o ff
li st Pe rs on
of f;
e xt ra ct lc of f);
ex tr ac t(l c,o ff
f or _e ac h(o ff be gi n(),o ff en d(),P ri nt _n am e(c ou t));
fo r_ ea ch of f.b eg in
of f.e nd
Pr in t_ na me co ut
}

Writing P ri nt _n am e is left as an exercise (§18.13[4]).
Pr in t_ na me
The f or _e ac h() algorithm is classified as nonmodifying because it doesn’t explicitly modify a
fo r_ ea ch
sequence. However, if applied to a non-c on st sequence f or _e ac h()’s operation (its third arguco ns t
fo r_ ea ch
ment) may change the elements of the sequence. For an example, see d el et e_ pt r() in §18.6.2.
de le te _p tr

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.



Section 18.5.2

The Find Family

525

18.5.2 The Find Family [algo.find]
The f in d() algorithms look through a sequence or a pair of sequences to find a value or a match on
fi nd
a predicate. The simple versions of f in d() look for a value or for a match with a predicate:
fi nd
t em pl at ete mp la te cl as s In cl as s T> In fi nd In fi rs t, In la st co ns t T& va l)
t em pl at e<c la ss I n, c la ss P re d> I n f in d_ if In f ir st I n l as t, P re d p ;
te mp la te cl as s In cl as s Pr ed In fi nd _i f(I n fi rs t, In la st Pr ed p)

The algorithms f in d() and f in d_ if return an iterator to the first element that matches a value and
fi nd
fi nd _i f()
a predicate, respectively. In fact, f in d() can be understood as the version of f in d_ if
fi nd
fi nd _i f() with the
predicate ==. Why aren’t they both called f in d()? The reason is that function overloading cannot
fi nd
always distinguish calls of two template functions with the same number of arguments. Consider:
b oo l p re d(i nt ;
bo ol pr ed in t)
v oi d f ve ct or bo ol f)(i nt
vo id f(v ec to r<b oo l(*f in t)>& v 1, v ec to r

v1 ve ct or in t>& v 2)
v2
{
f in d(v 1.b eg in ,v 1.e nd ,p re d);
fi nd v1 be gi n() v1 en d() pr ed
// find ‘pred’
f in d_ if v2 be gi n(),v 2.e nd ,p re d);
fi nd _i f(v 2.b eg in
v2 en d() pr ed
// find int for which pred() returns true
}

If f in d() and f in d_ if
fi nd
fi nd _i f() had had the same name, surprising ambiguities would have resulted. In
general, the _ if suffix is used to indicate that an algorithm takes a predicate.
_i f
The f in d_ fi rs t_ of algorithm finds the first element of a sequence that has a match in a second
fi nd _f ir st _o f()
sequence:
t em pl at e<c la ss F or c la ss F or 2>
te mp la te cl as s Fo r, cl as s Fo r2
F or f in d_ fi rs t_ of Fo r f ir st F or l as t, F or 2 f ir st 2, F or 2 l as t2 ;
Fo r fi nd _f ir st _o f(F or fi rs t, Fo r la st Fo r2 fi rs t2 Fo r2 la st 2)
t em pl at ete mp la te cl as s Fo r, cl as s Fo r2 cl as s Bi nP re d>
F or f in d_ fi rs t_ of Fo r f ir st F or l as t, F or 2 f ir st 2, F or 2 l as t2 B in Pr ed p ;
Fo r fi nd _f ir st _o f(F or fi rs t, Fo r la st Fo r2 fi rs t2 Fo r2 la st 2, Bi nP re d p)

For example:

i nt x = { 1 3,4 };
in t x[]
1,3 4
i nt y = { 0 2,3 4,5
in t y[]
0,2 3,4 5};
v oi d f
vo id f()
{
i nt p = f in d_ fi rs t_ of x,x 3,y y+5 ;
in t*
fi nd _f ir st _o f(x x+3 y,y 5)
i nt q = f in d_ fi rs t_ of p+1 x+3 y,y 5);
in t*
fi nd _f ir st _o f(p 1,x 3,y y+5
}

// p = &x[1]
// q = &x[2]

The pointer p will point to x 1] because 3 is the first element of x with a match in y Similarly, q
x[1
y.
will point to x 2].
x[2
The a dj ac en t_ fi nd algorithm finds a pair of adjacent matching values:
ad ja ce nt _f in d()
t em pl at ete mp la te cl as s Fo r> Fo r ad ja ce nt _f in d(F or fi rs t, Fo r la st
t em pl at e

te mp la te cl as s Fo r, cl as s Bi nP re d> Fo r ad ja ce nt _f in d(F or fi rs t, Fo r la st Bi nP re d p)

The return value is an iterator to the first matching element. For example:

The C++ Programming Language, Third Edition by Bjarne Stroustrup. Copyright ©1997 by AT&T.
Published by Addison Wesley Longman, Inc. ISBN 0-201-88954-4. All rights reserved.