Nicolai M. Josuttis: solutions in time  The C++ Standard Library: Errata for 1st and 2nd Printing

The C++ Standard Library - A Tutorial and Reference

Errata for the 1st and 2nd Printing
Jun 09, 2001

This is the errata for the 1st and 2nd printing of the book The C++ Standard Library by Nicolai M. Josuttis. It covers all errors that were found until the 5th printing came out. Thus, you will find additional errors in the erratas for later printings.

The errata is organized in the following way:
- It starts with the problem of incomplete pages (1st printing only)
- It continues with technical errors
- It ends with typos

Please note: This list may portray the book as containing many errors. But keep in mind that the book has about 800 pages with about 240.000 words. As I am not perfect I couldn't do better, and in my opinion it is severe to expect significantly fewer bugs. To cite one reader: "Thanks again and I'm going to write a short review of the book for Amazon contradicting whoever said it had lots of errors".


Incomplete Pages

Unfortunately, parts of some pages are missing (we still don't know how this could happen). Here, you can get the incomplete pages as individual files for each page or as one file for all missing pages in different formats.

Incomplete pages as PostScript files:
- Section 4.5, page 69, as PostScript file (171kB)
- Section 5.9.1, page 129, as PostScript file (171kB)
- Section 6.6.2, page 202, as PostScript file (173kB)
- All incomplete pages as one PostScript file (178kB)

Incomplete pages as PDF files:
- Section 4.5, page 69, as PDF file
(28kB)
- Section 5.9.1, page 129, as PDF file
(31kB)
- Section 6.6.2, page 202, as PDF file
(32kB)
- All incomplete pages as one PDF file
(53kB)

Use the popup menu of your browser (right mouse button and "Save Link As...") to download the files.


Errors

Page 12 and 13, Section 2.2.1
On both pages replace:
    template <class T>
    class MyClass<T> {
by:
    template <class T>
    class MyClass {


Page 27, Section 3.3.1
The text states unexpected() as global function ("the global function unexpected()"). This can lead to confusion because it is globally accessible but defined in namespace std. So, strike "global" in the text.


Pages 29/30, Section 3.3.2
The qualification with std:: is missing on several places of example code:
-
In the middle of page 29 you have to qualify exception, cerr, and endl.
- On top of page 30 you have to qualify string and out_of_range.


Page 58, Section 4.2.6
The sample implementation of class auto_ptr contains a bug. In the middle of page 58, replace reset(r.yp) by reset(rhs.yp).


Page 62, Section 4.3
In front of the specialization of the numeric limits for type float a declaration that states that this is a template specialization is missing. Thus, the correct definition has to be as follows:

namespace std {
    template<> class numeric_limits<float> {
        ...
    };
}


Page 140, Section 5.11.2:
Replace
    void insert (const Cont& coll, Iter pos, const T& value)
by
    void insert (Cont& coll, const Iter& pos, const T& value)


Page 145, Section 6.1.2, Table 6.1:
Replace
    c1 = c2 | Assigns all elements of c1 to c2
by
    c1 = c2 | Assigns all elements of c2 to c1


Page 149, Section 6.2.1:
Replace
    capacity() returns the number of characters
by
    capacity() returns the number of elements


Page 159, Section 6.2.6
In the example at the bottom of the page, Substitue c.at(5) by c[5] because in contrast to the following text c.at(5) would throw an exception instead of causing undefined behavior if no sixth element exists.


Page 176, Section 6.5.1, Footnote 17:
Of course, the goal of "red-black trees is it to be "nearly" balanced. So, replace "at least twice as long" by "at most twice as long".


Page 202, Section 6.6.2
c.insert(pos,elem) doesn't return whether it succeeded. Thus, strike "and whether it succeeded" in the second row of Table 6.31.


Page 205, Section 6.6.2
The second example and the following text contain some errors:
- Remove the declaration of tmp_pos.
- Replace each occurence of identifier c by coll.
-
Replace the following sentence before section 6.6.3 by:

Note that pos++ increments pos so that it refers to the next element but yields a copy of its value on entry. Thus, pos doesn't refer to the element that is removed when erase() is called.


Page 219, Section 6.7.2
In cont/carray.hpp, size_t and ptrdiff_t has to get qualified by std::.


Page 235, Section 6.10.3:
lower_bound() returns the first position that is equal to or greater than a value instead of less than or equal to a value.


Page 273, Section 7.4.2
In iter/backins.cpp there is a nasty problem with the following statement:

  copy (coll.begin(), coll.end(),   // source
        back_inserter(coll));       // destination

Because the back inserter inserts elements into a vector, these insertions might invalidate all other iterators referring to the same vector. Thus, the algorithm invalidates the passed source iterators while running. To avoid this behavior, you have to reserve enough space so that the reallocation won't happen. So, insert before the statement above:

  // reserve enough memory to avoid reallocation
 
coll.reserve (2*coll.size());


Page 278, Section 7.4.3:
Of course, ostream iterators operate by using operator << (not operator >>).


Page 279, Section 7.4.3
In iter/ostriter.cpp, the following include directive for class ostream_iterator is missing:

#include <iterator>


Page 288, Section 7.5.2
At the definition of MyIterator, ptrdiff_thas to get qualified by std::.


Page 303, Section 8.1.4
In example fo/removeif.cpp replace the comma at the end of the call of remove_if() by a semicolon.


Page 307, Section 8.2.2
Thoughout this section I state that member function for mem_fun_ref and mem_fun have to be constant member functions. This is not true. There is only a bug in combination with bind1st and bind2nd. Thus,

For example:

class Elem {
  public:
    void print (int i) const { }
    void modify (int i) { }
};

int main()
{
    vector<Elem> coll(2);
    for_each (coll.begin(), coll.end(),
              bind2nd(mem_fun_ref(&Elem::print),42));   // OK
   
for_each (coll.begin(), coll.end(),
              bind2nd(mem_fun_ref(&Elem::modify),42));  // ERROR
}


Page 315, Section 8.3.1
In fo/compose1.cpp the header file <iterator> for ostream_iterator is missing.


Page 319, Section 8.3.2
In fo/compose3.cpp the header file <cctype> for the C version of toupper() is missing.


Page 329, Section 9.2.2
Replace "stable_sort() is also based historically on heapsort" by "stable_sort() is based historically on mergesort".


Page 353, Section 9.5.3:
The complexity of find_first_of() is: at most, numberOfElements * numberOfSearchElements comparisons or calls of op().


Page 354, Section 9.5.3
Replace adjacent_find_if by adjacent_find (adjacent_find() is overloaded with both forms).


Page 358, Section 9.5.4
The second form of mismatch() returns the first corresponding elements for which the binary predicate op(elem,cmpElem) yields false. Thus, change last word of the second bullet.


Page 370, Section 9.6.3:
You can't use insert iterators as arguments for swap_ranges() because insert iterators aren't forward iterators (but output iterators). Thus, strike "or that insert iterators are used".
In addition, a statement is missing that both ranges shall not overlap.


Page 381, Section 9.7.2
As the description states, unique()returns the logical new end of the sequence. Thus for both forms of unique(), change the return type void to ForwardIterator.


Page 391, Section 9.8.3
next_permutation() and prev_permutation() return false, if the elements have "normal" order and true otherwise. Thus, change true and false of the third bullet and in the footnote.


Page 413, Section 9.10.1:
lower_bound() returns the first position that is equal to or greater than a value instead of less than or equal to a value.


Pages 465-466, Section 10.4.2:
In the discussion of bitset operations, the throws out_of_range condition should be "if idx >= size()" rather than "if idx > size()".


Page 468, Section 10.4.2:
In the example code for to_string(), replace "bitset b;" by "bitset<50> b;".


Page 468,469, Section 10.4.2:
Some missing facts of the I/O operatrors for bitsets:
- Both I/O operators return strm.
- operator << uses to_string() (see page 468)


Page 478, Section11.1.2
On the last row, replace with a signed type by with an unsigned type.


Page 489-517, Sections 11.2.8 - 11.3.7
some missing qualifications with std::


Page 493, Section 11.2.10
Of course, if width() is greater than 0, operator << writes at least width() characters.


Page 493, Section 11.2.10
getline() does not ignore leading whitespaces. Thus, replace

    This function ignores leading whitespaces and reads all characters until ...
by
    This function reads all characters (including leading whitespaces) until ...


Page 504, Section 11.2.14
In string/icstring.hpp:
-
size_t has to get qualified by std::
- Preprocessor directives to enable multiple includes are missing
- operator << should be declared as inline
See string/icstring.hpp for an updated version.


Page 524, Section 11.3.10
Of course, if strm.width() is greater than 0, operator << writes at least width() characters.


Page 525, Section 11.3.10
getline() does not respect width(). So, strike the first item of the list that describes how long characters are extracted by getline(). This was a simple error due to a copy-and-paste from operator >>.


Page 533, Section 12.1.2
The computed assignment operators for complex do not operate only on real parts. Thus, strike "the real part of" and "The imaginary part of both operands is left unchanged".


Page 534, Section 12.1.2
Koenig Lookup (see page 17) allows to initialize c2 without std qualification:

std::complex<double> c2(conj(c1));


Page 539, Section 12.1.2
Appending a zero byte at the end of the string s in the implementation of the output operator for complex<> is wrong. Thus, remove " << std::ends".


Page 544, Section 12.1.3:
Some missing facts of the I/O operatrors for complex<>:
- Both I/O operators return strm.


Page 595, Section 13.3.2
Replace std::complex c; by std::complex<double> c;


Page 605, Section 13.4.4:
The forward declaration of readAndProcessSum() in io/summain.cpp is not correct.
Replace
    double MyLib::readAndProcessSum (std::istream&);
by
    namespace MyLib {
        double readAndProcessSum (std::istream&);
    }


Pages 608, Section 13.5.1
There is another difference between get() and getline() for input streams: If getline() reads lines with more than count-1 characters, it sets failbit. Thus, to read again you have to call clear().


Pages 609 and 614, Sections 13.5.1 and 13.6.2:
There is a contratiction in the standard regarding istream::ignore(). Once int is used as type of the first argument, once streamsize is used. According to the current defect report list streamsize seems to be right. Thus, replace each occurence of
    numeric_limits<int>::max()
by
    std::numeric_limits<std::streamsize>::max()


Page 636, Section 13.9.2:
In io/cat2.cpp you can remove the call of file.clear(). This is because file.rdbuf() is used to print the contents of the file but rdbuf() can't manipulate the state of the stream (a stream buffer has no access to the streams that use it). Regarding this, the comment after the example is wrong.


Page 654, Section 13.12.1
Of course, the output of Fraction vat(16,100) is:  VAT: "16/100 "


Page 670, Section 13.13.3:
In io/outbuf1x.hpp substitue
  std::class traits = char_traits<charT>
by
  class traits = std::char_traits<charT>


Page 684, Section 13.14.3:
If you are using operator >> to read directly into a stream buffer, leading whitespace is skipped (however, this is a recent clarification in the standard, which might not be handled corrently in all compilers). So, in io/copy2.cpp to copy all standard input into standard output you have to change the statement into the following:

std::cin >> std::noskipws >> std::cout.rdbuf();


Page 707, Section 14.4.1
In the example of numeric parsing
-
replace std::ios_base::ios_state by std::ios_base::iostate
- add > before (loc) so that the line reads as follows:
      = std::use_facet<std::num_get<charT,InIt> >(loc);
See i18n/numget.cpp for a complete supplementary example program.


Page 714, Section 14.4.3
In Table 14.15 replace space in last row by none. In addition, last but second and last but third rows are identical.


Page 727, Section 15.1
Usually, you have to pass arguments to allocators and qualifications with std are missing. Thus, the examples have to be as follows:

// a vector with special allocator
std::vector<int,SpecialAlloc<int> > v;

// an int/float map with special allocator
std::map<int,float,less<int>,
         SpecialAlloc<std::pair<const int,float> > > m;

// a string with special allocator
std::basic_string<char,std::char_traits<char>,SpecialAlloc<char> > s;

and:

// special string type that uses special allocator
typedef std::basic_string<char,std::char_traits<char>,
                          SpecialAlloc<char> > xstring;

// special string/string map type that uses special allocator
typedef std::map<xstring,xstring,less<xstring>,
                 SpecialAlloc<std::pair<const xstring,xstring> > > xmap;


Page 731, Section 15.2
In the example for temporary buffers, ptrdiff_t has to get qualified by std::.


Page 737, Section 15.4
In util/defalloc.hpp replace delete((void*)p)) by delete((void*)p).


Page 740, Section 15.5.2
The member function destroy() for allocators, of course, calls the destructor. Thus, replace

by


Section 15.4
You can find an example of a user-defined allocator at http://www.josuttis.com/cppcode/.


Typos

Page xix: s/fogive/forgive/

Page xix: s/Nathan Meyers/Nathan Myers/

Page xix: s/Steve Rumbsby/Steve Rumsby/

Page xix: s/comp.std.c++.moderated/comp.lang.c++.moderated/

Page 5: s/not yet confirm to it/not yet conform to it/

Page 10: s/Templates classes/Template classes/

Page 11: s/except it is/except if it is/

Page 12: s/any template type, then as long as/any template type then, as long as/

Page 15: s/excetion-condition/exception-condition/

Page 16: s/That a function not throw/That a function does not throw/

Page 20, top: s/it it always/it is always/

Page 20, bottom: s/to to define/to define/

Page 29: s/Section 2, page 480/Section 11.2.1, page 480/

Page 46: s/if the auto_ptr should refer to the same object/if the auto_ptr should not change the object to which it refers/

Page 80: s/as long as it returns true/as long as it returns false/

Page 83: s/a STL container/an STL container/

Page 87: s/arbitray/arbitrary/

Page 100: s/search for pos35/search for 35/

Page 109: s/to cout by calling operator >>/to cout by calling operator <</

Page 114: s/the real ends/the real end/

Page 124: s/that behave as functions/that behave like functions/

Page 133: s/multiply<int>/multiplies<int>/

Page 136: s/reference semnatics/reference semantics/

Page 137: /The most security/The highest security/

Page 143: s/a type of reference manual/a kind of reference manual/

Page 143: s/bitmaps/bitsets/

Page 144: s/rather than managing references to it/rather than managing references to them/

Page 148: s/the implementation use a/the implementation uses a/

Page 149: s/are deleted or changed/are deleted/

Page 175: s/the type is defined as a template class/the types are defined as class templates/

Page 182: s/the with following arguments/with the following arguments/

Page 183: s/multisets allows duplicates/multisets allow duplicates/

Page 185: s/exceptions handling/exception handling/

Page 194: s/the type is defined as a template class/the types are defined as class templates/

Page 204: s/multimap<string.float>/std::multimap<std::string,float>/

Page 204: s/that will you remove/that you will remove/

Page 217: s/sometime/sometimes/

Page 226: s/Table 6.9/Table 6.33/

Page 252: s/for this reasen/for this reason/

Page 258,259: s/coll.sort(...)/sort(...)/ (twice)

Page 260: s/step three elements backward/step one element backward/

Page 277: s/of a useful supplementation/of the need for a supplementation/

Page 283: s/someone who you respect./someone whom you respect./

Page 313: s/for some possible names and the names/for the names/

Page 324: s/count()_if()/count_if()/

Page 326: s/replace()_if()/replace_if()/

Page 327: s/remove_copy()_if()/remove_copy_if()/

Page 344: s/without rest/without remainder/

Page 345: s/find three consecutive elements with value 4/find four consecutive elements with value 3/

Page 346: s/find three consecutive elements with value greater than 4/find four consecutive elements with value greater than 3/

Page 371: s/swap first four elements/swap elements of coll1 with corresponding elements of coll2/

Page 379: s/removed: :/removed: / (twice)

Page 409: s/element-b-element/element-by-element/

Page 409: s/They may have significant better performance/They may have significantly better performance/

Page 429, second bullet: s/The first form/The second form/

Page 446: s/back() returns ... (the element that was inserted first)/back() returns ... (the element that was inserted last)/

Page 478: s/as an optional second character argument/as an optional third character argument/

Page 482: s/Word processing/Text processing/ (twice)

Page 506: s/vectors implementations/vector implementations/

Pages 512-523: s/Note that cstr may not be a null pointer/Note that cstr must not be a null pointer/

Page 513: s/the contents of buf may be not/the contents of buf might not be/

Page 582: s/completely different/completely differently/

Page 585: s/output to and output from/output to and input from/

Page 586: s/The shift operators << for input and >> for output/The shift operators << for output and >> for input/

Page 589: s/Using stream buffers/By using stream buffers/

Page 594: s/less priority/lower priority/

Page 611: s/the read character is accessed simply by using the dereference operator/the read character is accessed simply by passing c by reference/

Page 624: s/1.23456789e-001/1.23456789e-01/

Page 627: s/provides three class templates/provides four class templates/

Page 634: s/The member function open() does not clear the state flags. open() open() never clears any state flags./open() never clears any state flags./

Page 658: s/by using the stream buffer's member function sputn()/by using the stream's member function write()/

Page 663: s/n character/n characters/

Page 664: s/pubseekpos(pos/pubseekpos(pos)/

Page 676: s/eback(), gptr() and egptr()/eback, gptr(), and egptr()/

Page 693: s/(JIT)/(JIS)/

Page 704: s/publically/publicly/ (twice)

Page 705: s/instant/instance/

Page 720: s/To understanding/To understand/

Page 721: s/a very few/very few/

Page 723: s/need to produce/needed to produce/


Home of the C++ Library book