Errata for The C++ Programming Language(SE)(涵盖影印版至今的所有已知错误)

类别:VC语言 点击:0 评论:0 推荐:
Errata for The C++ Programming Language(SE)

Here, I made a packet of all the erratas for the book "The C++ Programming Language (Special Edition)" from the first print of the Sepcial Edition, so it should cover all the erratas of the PhotoCopy Edition sold in China. While looking through these erratas, please ATTENTION Stroustrup's words:"For brevity, I use the old replacement syntax: s/old/new/".

- bood([email protected])
- 2002/04/02

Errors and Clarifications

Chapter 1:

pg 13 s/(sec B.2)/(with a few minor exceptions; see sec B.2)/

Chapter 3:

pg 55 s/Entry& e =/const Entry& e =/

Chapter 4:

pg 76 A better version of the example:

#include < limits>
#include < iostream>

int main()
std::cout << "largest float == " << std::numeric_limits< float>::max()
<< ", char is signed == " << std::numeric_limits< char>::is_signed << '\n';

pg 77 Replace the 5th paragraph with: "An enumerator can be initialized by a constant-expression (C.5) of integral type (4.1.1). The range of an enumeration holds all the enumeration's enumerator values rounded up to the nearest larger binary power minus 1. The range goes down to 0 if the smallest enumerator is non-negative. If the smallest enumerator is negative, the range goes down to -(1+max) where max is the largests value in the positive part of the range. This defines the smallest bit-field capable of holding the enumerator values using the conventional two's complement representation. For example:"

Chapter 6:

pg 109-110: s/left=left+term() and left=left-term) could have been used without changing the meaning of the program. However, left+=term() and left-=term(/ left=left+term(true) and left=left-term(true) could have been used without changing the meaning of the program. However, left+=term(true) and left-=term(true)/

pg 125 s/The increment operators are particularly useful for incrementing and decrementing variables in loops./The ++ and -- operators are particularly useful for incrementing and decrementing variables in loops./

pg 129 Add comments to first example:

void* operator new(size_t); // allocate space for individual object
void operator delete(void* p); // if (p) deallocate space allocated using operator new()
void* operator new[](size_t); // allocate space for array
void operator delete[](void* p); // if (p) deallocate space allocated using operator new[]()

pg 130 s/an enumeration to an integral type/an integral type to an enumeration/

pg 131 Clarification of the first paragraph after the first example: "The T(e) construct is sometimes referred to as a function-style cast. Unfortunately, for a built-in type T, T(e) is equivalent to (T)e (6.2.7). This implies that for many built-in types T(e) is not safe. ..."

pg 131 s/removing const qualifiers/removing const and volatile qualifiers/

pg 134: s/``does p point to a valid object,''/ ``does p point to a valid object (assuming proper initialization),''/

Chapter 7:

pg 146 s/21.2.1/21.3.2/

Chapter 8:

pg 193 add "++Driver::no_of_errors;" to each catch clause

pg 195 s/depending on where in a class stack/ depending on where in the function call stack/

Chapter 9:

pg 202: Improved last example:

#ifdef __cplusplus // for C++ compilers only (9.2.4)
namespace std { // the standard library is defined in namespace std (8.2.9)
extern "C" { // stdio functions have C linkage (9.2.4)
/* ... */
int printf(const char*, ...);
/* ... */
#ifdef __cplusplus
// ...
using std::printf; // make printf available in global namespace
// ...

Chapter 10:

pg 246 Replace the last sentence before 10.4.5 by: "Exceptions can be used to report failure to copy ( See E.3.3 for techniques for writing exception-safe copy operations."

pg 247 s/reverse order of construction./reverse order of construction after the body of the class' own destructor has been executed./

pg 251 replace the middle example with

void g()
vector< Table> v(10); // no need for a delete
vector< Table>* p = new vector< Table>(10); // use plain "delete" rather than "delete[]"

delete p;

Using a container, such as vector, is simpler than writing a new/delete pair. Furthermore, vector provides exception safety (Appendix E).

pg 258 s/

Chapter 11:

pg 265 s/basic type/built-in type (sec4.1.1)/

pg 273 s/basic type/built-in type/

pg 275 s/basic type/built-in type/ twice

pg 280 add the sentence "Scopes outside the innermost enclosing namespace scope are not considered." before the first "For example:" and replace the first example by:

class AE { /* ... */ }; // not a friend of Y

namespace N {
class X { /* ... */ }; // Y's friend

class Y {
friend class X;
friend class Z;
friend class AE;
class Z { /* ... */ }; // Y's friend

pg 280 Improved version of 4th paragraph: "Thus, a friend function should be explicitly declared in an enclosing scope or take an argument of its class or a class derived from that (13.6). If not, the friend cannot be called. For example:"

pg 284 s/string initialized (using copy constructor)/string initialized (using constructor)/

pg 288 s/return b;/return f;/

pg 290 replace the example using Y at the middle of the page by: Given a class Y for which ->, *, and [] have their default meaning and a Y* called p then

p->m == (*p).m // is true
(*p).m == p[0].m // is true
p->m == p[0].m // is true

pg 293 better:

class String {
struct Srep; // representation
Srep *rep;

class Cref; // reference to char

Chapter 13:

pg 335 s/const char[12]/const char v[12]/

pg 346 s/}/};/ twice in the first example

pg 346 Replace the last sentence after the long example by: "However, the definition of operations such as == and != must be expressed in terms of both the container and its elements, so the element type needs to be passed to the container template. The resulting container type is then passed to Basic_ops."

Chapter 14:

pg 369 better:

X* p3 = new(&buffer[10]) X; // place X in buffer (no deallocation needed)
X* p4 = new(&buffer[11]) X[10];

pg 380 after the first paragraph add: "The clone() function is used to allocate a copy of an exception on free store. This copy will survive the exception handler's cleanup of local variables."

Chapter 15:

pg 401 add as the last sentence before "A potential problem is that now a BB_popup_ival_slider can't be implicitly converted to an Ival_slider."

pg 408 s/If p is of type T* or of an accessible base class of T,/ If p is of type T* or of a type D* where T is a base class of D,/

pg 414 replace the first paragraph with: "It is not possible to cast to a private base class, and ``casting away const '' (or volatile) requires a const_cast (6.2.7). Even then, using the result is safe only provided the object wasn't originally declared const (or volatile) ("

pg 415 Replace the second paragraph with: "If the value of a pointer or a reference operand of a polymorphic type is 0, typeid() throws a bad_typeid exception. If the operand of typeid() has a non-polymorphic type or is not an lvalue, the result is determined at compile time without evaluating the operand expression."

pg 416 s/map< const char*, Layout> layout_table;/ map< string, Layout> layout_table;/

pg 422 Improve example:

void Employee::operator delete(void* p, size_t s)
if (p) { // delete only if p!=0; see sec6.2.6, sec6.2.6.2
// assume `p' points to `s' bytes of memory allocated by Employee::operator new()
// and free that memory for reuse

pg 342 s/static_cast/reinterpret_cast/ twice

Chapter 16:

pg 431 Replace the paragraph before for the table by "A standard header with a name starting with the letter c is equivalent to a header in the C standard library. For every header <X.h> defining part of the C standard library in the global namespace and also in namespace std, there is a header <cX> defining the same names in the std namespace only (see 9.2.2)."

pg 433 s/s.18.7/D.4.4.1/ on the line for < ctime>

pg 434 s/fabs(),//

pg 457 s/vector tmp/vector< tmp>/

Chapter 17:

pg 482 Improvement to reflect standard corrigendum:

template < class T1, class T2> pair< T1,T2> std::make_pair(T1 t1, T2 t2)
return pair< T1,T2>(t1,t2);

pg 485 s/value_type;/value_type,/

pg 493 the argument to bitset'c onstructor requires a conversion to string:

bitset< 10> b4(string("1010101010")); // 1010101010
bitset< 10> b5(string("10110111011110",4)); // 0111011110
bitset< 10> b6(string("10110111011110",2,8)); // 0011011101

bitset< 10> b7(string("n0g00d")); // invalid_argument thrown
bitset< 10> b8 = string("n0g00d"); // error: no string to bitset conversion

pg 496 s/size_t/ptrdiff_t/ twice

pg 496 add after the definition of c_array: "For compatibility with arrays, I use the signed ptrdiff_t (16.1.2) rather than the unsigned size_t as the subscript type. Using size_t could lead to subtle ambiguities when using [] on a c_array."

Chapter 18:

pg 524 s/operator()(const Club&)/operator()(const Club&) const/

pg 535 s/sort(off.begin(),off.end(),Person_lt)/off.sort(off,Person_lt)/

pg 536 /class located_in {/class located_in : public unary_function< Club,bool> {

pg 536 s/output_iterator/ostream_iterator/

pg 538 replace the second example with

For a call random_shuffle(b,e,r), the generator is called with the number of elements in the sequence as its argument: r(e-b). The generator must return a value in the range [0,e-b). If My_rand is such a generator, we might shuffle a deck of cards like this:

void f(deque< Card>& dc, My_rand& r)
// ...

Chapter 19:

pg 562 s/ getting a const iterator for a non-const iterator./ getting a const iterator for a non-const container./

pg 563 s/d< curr-c->begin()/d< -(curr-c->begin())/ twice

pg 568 Add at the end of the first paragraph: "Note that deallocate() differs from operator delete() (sec 6.2.6) in that its pointer argument may not be zero."

Chapter 20:

pg 591 replace the first sentence by "When a position and a size are supplied for a string in a compare(), only the indicated substring is used. For example,,n,s2) is equivalent to string(s,pos,n).compare(s2)."

pg 596 add to class basic_string:

void clear(); // erase all characters

pg 599: replace the last two declarations with:

size_t strspn(const char* p, const char* q); // number of char in p before a char not in q
size_t strcspn(const char* p, const char* q); // number of char in p before a char in q

pg 600-601 Expand the section describing conversion functions to:

In < stdlib.h> and < cstdlib> , the standard library provides useful functions for converting strings representing numeric values into numeric values. For example:

double atof(const char* p); // convert p[] to double (``alpha to floating'')
double strtod(const char* p, char** end); // convert p[] to double (``string to double'')
int atoi(const char* p); // convert p[] to int, assuming base 10
long atol(const char* p); // convert p[] to long, assuming base 10
long strtol(const char* p, char** end, int b); // convert p[] to long, assuming base b

These functions ignore leading whitespace. If the input string doesn't represent a number, zero is returned. For example, the value of atoi("seven") is 0.

If end is non-zero in a call strtol(p,end,b), the position of the first unread character in the input string is made available by assigning it to *end. If b==0, a number is interpreted the way a C++ integer literal is (4.4.1); for example, a 0x prefix means hexadecimal, 0 means octal, etc.

It is undefined what happens if atof(), atoi(), or atol() converts a value that cannot be represented as its respective return type. If the input string for strtol() represents a number that cannot be represented as a long int or if the input string for strtod() represents a number that cannot be represented as a double, errno (16.1.2, 22.3) is set to ERANGE and an appropriately huge or tiny value is returned.

Except for the error handling, atof(s) is equivalent to strtod(s,0), atoi(s) is equivalent to int(strtol(s,0,10)), and atol(s) is equivalent to strtol(s,0,10).

Chapter 21:

pg 619 somewhere add "If a get() or getline() function doesn't read and remove at least one character from the stream, setstate(failbit) is called, so that subsequent reads from the stream will fail (or an exception is thrown (21.3.6))." also modify the example to:

void subtle_error()
char buf[256];

while (cin) {
cin.get(buf,256); // read a line
cout << buf; // print a line
// Oops: forgot to remove '\en' from cin - the next get() will fail

pg 621 s/badbit/failbit/

pg 621 Add at the bottom: "If a format error is found, the stream state is set to failbit. The state is not set to badbit because the stream itself isn't corrupted. A user could reset the stream (using clear()) and might be able to skip past the problem and extract useful data from the stream."

pg 623 replace the handler by

catch(ios_base::failure) { // ok: end of file reached

pg 629 better:

basic_ostream< Ch,Tr>& operator<<(basic_ostream< Ch,Tr>& os, const smanip& m)
return os;

pg 629 better:

ios_base& set_precision(ios_base& s, int n) // helper
s.precision(n); // call the member function
return s;

pg 632 s/noskipws()/unsetf(ios_base::skipws)/ twice

pg 633 s/smanip& m)/const smanip& m)/

pg 635 s/<< d << endl;/<< 1.41421 << endl;/

pg 652 s/with an initial 0x//

pg 652 s/with an initial 0X//

pg 646 s/eptr/egptr/ twice

Chapter 22:

pg 670 see a complete example of Slice_iter and matrix for a better idea of what the errata adds up to.

pg 669 s/int i/size_t i/

pg 671 the last example used a non-standard feature. Better:

v_even *= v_odd; // multiply element pairs and store results in even elements
v_odd = 0; // assign 0 to every odd element of d

pg 674 s/int i/size_t i/ twice

pg 683 a better operator*():

valarray< double> operator*(const Matrix& m, valarray< double>& v)
valarray< double> res(m.dim2());

for (size_t i = 0; i< m.dim2(); i++) {
const Cslice_iter< double>& ri = m.row(i);
res[i] = inner_product(ri,ri.end(),&v[0],double(0));
return res;

pg 684 a better operator*():

valarray< double> operator*(valarray& v, const Matrix& m)
valarray< double> res(m.dim1());

for (size_t i = 0; i< m.dim1(); i++) {
const Cslice_iter< double>& ci = m.column(i);
res[i] = inner_product(ci,ci.end(),&v[0],double(0));
return res;

Chapter 25:

pg 788 s/Circle*/Circle/ in 2.

pg 788 s/Shape*/Shape/ in 2.

Appendix A:

pg 808 s/extern const volatile clock;/extern const volatile long clock;/

pg 809: In class-head replace

class-key nested-name-specifier template template-id base-clause(opt

class-key nested-name-specifier(opt template-id base-clause(opt

pg 811 s/indentifier(opt) = template-name/indentifier(opt) = id-expression/

pg 811 in "template-argument:" s/template-name/id-expression/

Appendix C:

pg 851 replace the first example by

void Z2::f(Y1* py1, Y2* py2, Y3* py3)
X* px = py1; // ok: X is a public base class of Y1
py1->a = 7; // ok
px = this; // ok: X is a protected base of Y2, and Z2 is derived from Y2
a = 7; // ok
px = py2; // error: X is a protected base of Y2, and Z2 is derived from Y2,
// but we don't know that py2 is a Z2 or how Y2::X is used in a non-Z2 object
py2->a = 7; // error: Z2 doesn't know how Y2::a is used in a non-Z2 object
px = py3; // error: X is a private base of Y3
py3->a = 7; // error

pg 855: replace the first two sentences of the paragraph following the first example of C.13.3 by: "To declare a template as a template parameter, we must specify its required arguments. For example, we specify that Xrefd 's template parameter C is a template class that takes a single type argument. If we didn't, we wouldn't be able to use specializations of C."

pg 858 add "template< class T> before "void k("

pg 867 s/template Calls_foo< Shape*>::constraints();/ template void Calls_foo< Shape*>::constraints(Shape*);/

pg 895 s/: num_put/std::num_put/

pg 898 s/my_numpunct/My_punct/

pg 910 add before D.4.4.4: A _byname version (D.4, D.4.1) of time_put is also provided:

template < class Ch, class Out = ostreambuf_iterator< Ch> >
class std::time_put_byname : public time_put< Ch,Out> { /* ... */ };

pg 912 s/time_put()/time_put::put()/ twice

pg 912 replace the last paragraph with: A _byname version (D.4, D.4.1) time_get is also provided:

template < class Ch, class In = istreambuf_iterator< Ch> >
class std::time_get_byname : public time_get< Ch,In> { /* ... */ };

pg 915 s/Date_format< char>::/Date_format::/

pg 918 s/dateorder()/date_order()/

pg 919 s/order = dateorder();/order = date_order();/

pg 919 s/tmp->tm_mday = val[1];/tmp->tm_mday = val[2];/

pg 924 s/widen(narrow('x')) == 'x'/widen(narrow('x'),0) == 'x'/

pg 926 s/out() encountered/in() encountered/

pg 928 add "char ch;" before the while-statement

Appendix D:

pg 871 s/istream& fout/ostream& fout/ twice

pg 880 Change the comment in the example:

sort(v.begin(),v.end()); // sort using < to compare elements

pg 884 s/falilure state/fail state/

890 s/cs2+size()/cs2+s2.size()/

pg 890 s/cs2+cs2.size()/cs2+s2.size()/ twice

pg 891 s/public virtual function do_compare()/protected virtual function do_compare()/

pg 891 s/cs2+cs2.size()/cs2+s2.size()/

pg 893 s/: numpunct< char>(r) { }/: std::numpunct< char>(r) { }/

pg 894 The output at the default format and precision is:

style A: 12345678 *** 1.23457e+06
style B: 12 345 678 *** 1,23457e+06

pg 895 s/&s[pos]/s.begin()+pos/

pg 898 s/.get(os,/.get(*this,/

pg 896 s/fill()/this->fill()/

pg 898 s/eos,state/eos,*this,state/

pg 899 s/DKr/DKK/

pg 899 s/money_punct's/moneypunct's/

pg 900 s/FrF/FRF/

pg 900 s/DKr/DKK/ twice

pg 900 s/Usually, the last character is a space./ The last character is a terminating zero./

pg 901 s/DKr/DKK/ twice

pg 901 Correct:

char_type do_decimal_point() const { return '.'; }
char_type do_thousands_sep() const { return ','; }

pg 904 A better input function:

istream& operator>>(istream& s, Money& m)
istream::sentry guard(s); // see 21.3.8
if (guard) try {
ios_base::iostate state = 0; // good
istreambuf_iterator< char> eos;
string str;

use_facet< money_get< char> >(s.getloc()).get(s,eos,true,state,str);

if (state==0 || state==ios_base::eofbit) { // set value only if get() succeeded
long int i = strtol(str.c_str(),0,0); // for strtol(), see 20.4.1
if (errno==ERANGE)
state |= ios_base::failbit;
m = i; // set value only if conversion to long int succeeded
catch (...) {
handle_ioexception(s); // see D.4.2.2
return s;

I use the get() that reads into a string because reading into a double and then converting to a long int could lead to loss of precision.

pg 904 s/d = dd/m = dd/

pg 909 s/sloppy: no protection against buffer overflow/ sloppy: hope strftime () will never produce more than 20 characters/

pg 912 s/The default reads a time/The default get_date() reads a date/

pg 912 s/Month(x.tm_mon)+1/Month(x.tm_mon+1)/

pg 915 s/(f.put( ... .failed)/(f.put( ... .failed())/

pg 915 s/const { curr=p;/{ curr=p;/ twice

pg 915 s/see _io.sentry/see 21.3.8/

pg 916 s/Month(x.tm_mon)+1/Month(x.tm_mon+1)/

pg 916 s/std::time_get< Ch>/std::time_get< Ch,In>/

pg 917 a better getval():

template< class Ch, class In>
In Date_in< Ch,In>::getval(In b, In e, ios_base& s, ios_base::iostate& r, int* v, Vtype* res) const
// read part of Date: number, day_of_week, or month. Skip whitespace and punctuation.
const ctype< Ch>& ct = use_facet< ctype< Ch> >(s.getloc()); // ctype is defined in D.4.5
Ch c;

*res = novalue; // no value found

for (;;) { // skip whitespace and punctuation
if (b == e) return e;
c = *b;
if (!(,c) ||,c))) break;

if (,c)) { // read integer without regard for numpunct
int i = 0;

do { // turn digit from arbitrary character set into decimal value:
static char const digits[] = "0123456789";
i = i*10 + find(digits,digits+10,ct.narrow(c,' '))-digits;
c = *++b;
} while (,c));

*v = i;
*res = unknown; // an integer, but we don't know what it represents
return b;

if (,c)) { // look for name of month or day of week
basic_string< Ch> str;
while (,c)) { // read characters into string
str += c;
if (++b == e) break;
c = *b;

tm t;
basic_stringstream< Ch> ss(str);
typedef istreambuf_iterator< Ch> SI; // iterator type for ss' buffer
get_monthname(ss.rdbuf(),SI(),s,r,&t); // read from in-memory stream buffer
if ((r&(ios_base::badbit|ios_base::failbit))==0) {
*v= t.tm_mon;
*res = month;
r = 0;
return b;

r = 0; // clear state before trying to read a second time
get_weekday(ss.rdbuf(),SI(),s,r,&t); // read from in-memory stream buffer
if ((r&ios_base::badbit)==0) {
*v = t.tm_wday;
*res = dayofweek;
r = 0;
return b;
r |= ios_base::failbit;
return b;

pg 919 replace

template< class Ch, class In = istreambuf_iterator< Ch> >
In Date_in::do_get_date(

template< class Ch, class In>
In Date_in< Ch,In>::do_get_date(

pg 922 a better count_spaces():

int count_spaces(const string& s, const locale& loc)
const ctype< char>& ct = use_facet< ctype< char> >(loc);
int i = 0;
for(string::const_iterator p = s.begin(); p != s.end(); ++p)
if (,*p)) ++i; // whitespace as defined by ct
return i;

pg 922 s/|punct,c)/|ctype_base::punct,c)/

pg 922 s/std::ctype/std::ctype< Ch>/

pg 923 s/std::ctype/std::ctype< Ch>/

pg 927 s/always_no_conv/always_noconv/

pg 929 Correct:

void do_close(catalog cat) const
if (catalogs.size()<=cat) catalogs.erase(catalogs.begin()+cat);

pg 931 s/to_str(Season) ... of s/to_str(Season x) ... of x/

pg 932 replace to_str() by

const string& Season_io::to_str(Season x) const
return m->get(cat,x,"no-such-season");

pg 933 s/such as 12 May 1995/such as 12 5 1995/

Appendix E:

pg 939 s/rand()/(rand())/

pg 944 change

void destroy_elements() { for (T* p = v; p!=space; ++p) p->~T(); }

void destroy_elements() { for (T* p = v; p!=space; ++p) p->~T(); space=v; }

pg 945: After the second example, add: However, the default swap() implementation don't suit our needs for vector_base because it copies and destroys a vector_base. Consequently, we provide a specialization:

template< class T> void swap(vector_base< T>& a, vector_base& b)
swap(a.a,b.a); swap(a.v,b.v); swap(,; swap(a.last,b.last);


Chapter 1:

pg 10 umlauted o missing in Wikstr?m's name.

pg 19 s/conference/Conference/

Chapter 4:

pg 80 s/a vector/an array/

Chapter 5:

pg 105 s/arrays of char/array of char/

Chapter 8:

pg 168: s/separating the implementation of the interface/ separating the implementation from the interface/

Chapter 10:

pg 229 s/The keyword static is not be repeated/The keyword static is not repeated/

Chapter 11:

pg 288 s/ of the array/of the vector/

Chapter 13:

pg 349 s/the member of the set/the members of the set/

Chapter 14:

pg 355 s/, the program could:/, a function could/

pg 365 s/program now shrinks/function now shrinks/

pg 368 s/constutors/constructors/

pg 373 s/need to allocate/needs to allocate/

pg 380 s/delete p;/delete pe;/

Chapter 16:

pg 452 s/and initial_not() (is the initial letter different from p?)/ and initial_not(x) (is the initial letter different from x?)/

pg 468 s/criteria/criterion/

Chapter 18:

pg 521 s/Consequently, the standard library supplies two adapters to allow pointers to functions to be used together with the standard algorithms. in / Consequently, in the standard library supplies two adapters to allow pointers to functions to be used together with the standard algorithms./

pg 531 s/The the/The/

pg 542 s/comes first/come first/

Chapter 19:

pg 552 s/terms combinations/terms of combinations/

Chapter 20:

pg 590 s/interprete/interpret/

pg 602 s/c_str() produce/c_str() to produce/

pg 602 s/rather that/rather than/

Chapter 21:

pg 617 s/a call of is::operator void*()/a call of istream::operator void*() for is./

pg 630 s/A call width(n) function/A call width(n)/

pg 639 s/ and do experiment./ and experiment./

pg 652 s/pecision/precision/

pg 685 s/miniscule propability/minuscule probability/

Appendix B:

pg 815 s/to try port/try to port/

Appendix D:

pg 876 s/print_locale names/print_locale_names/

pg 880 s/rather then C-style strings./rather than C-style strings./

pg 892 s/_byname locale/_byname facet/

pg 899 s/amount/amount=/ five times in the output

pg 916 s/get_date() the Istream's/get_date() from the istream's/

pg 924 s/ctype locale/ctype facet/

pg 931 s/Season_io locale/ctype facet/

Appendix E:

pg 936 s/point of view a/point of view of a/

pg 952 s/T& vector< T,A >::emergency_exit()/void vector< T,A >::emergency_exit()/ twice

pg 959 s/The cost of completely protecting against an exception while moving elements in a vector be/ The cost of completely protecting against an exception while moving elements in a vector would be/

pg 960 s/associated containers/associative containers/

pg 962 s/application its types/application types/

pg 965 s/capable of throwing of/capable of throwing/

pg 965 s/that provide strong (E4)./that provide the strong guarantee (E4)./

pg 966 s/trivially type safe/trivially exception safe/