C++11StdLib  The C++ Standard Library, 2nd Edition: Errata for 1st and 2nd printings

The C++ Standard Library - A Tutorial and Reference, 2nd Edition

Errata
November 22, 2013

This is the errata of the first and second printing of the book The C++ Standard Library, 2nd Edition by Nicolai M. Josuttis. It covers all errors that were found until the 3rd printing of this edition came out. Thus, you will find additional errors in the erratas for later printings.

The errata is organized in the following way:
- The first part lists technical errors. They have a date entry for the last change to be able to identify new/modified errata entries when visiting this page from time to time.
- The second part lists typos (including stylistic changes due to consistency etc.)


Errors

Page 19/20 (3.1.5): 2012
Strictly speaking, you can't insert() the same element twice into a set. Thus, you should replace set by multiset in the examples motivating move semantics (three times).

Page 57 (4.6) paragraph after code: 2012
s/
The default allocator is used as.../An object of the default allocator type is used as.../

Page 61 Table 5.1 (5.1.1): 2012
The second declaration has to use "val1" and "val2" instead of "val1" and "val1". So replace the second and fourth "val1" by "val2".

Page 81 (util/sharedptr2.cpp): 2013-04-21
In the deleter, the deletion of the file stream fp is missing, which also closes the file, and there is an invalid dot in the first comment. So the correct implementation is:

void operator () (std::ofstream* fp) {
    delete fp;                     // close file
    std::remove(filename.c_str()); // delete file
}

And just as a clarification: The call of std::remove() is the call of a standard C function declared in <cstdio> to delete files. Unfortunatelly, I don't have these C functions described in the book and for this reason you also can't find an entry in the index for the remove() called here.

Page 95 bottom (5.2.4): 2013-03-05

s/static_pointer_cast<int*>(sp)/static_pointer_cast<int>(sp)/

Page 133 (5.4.4): 2013-01-07

After the first example, add:

To call each task, you could also simply call:
    // call each task:
    for (auto f : tasks) {
        f(33,66);
    }

Page 140 (5.6): 2013-01-07
In the declaration of class ratio<>, the declaration of type has to follow the declarations of num and den because it uses these members (this is also a bug in the C++11 Standard):

static constexpr intmax_t num;
static constexpr intmax_t den;
typedef ratio<num, den> type;

Page 146 after Table 5.21 (5.7.2): 2012
The default constructor for durations creates an undefined value. For this reason, you have to initialize ms by 0. In addition, two comments have the wrong value. Thus, the example is correct as follows:

std::chrono::milliseconds ms(0);    // 0 milliseconds (undefined value without (0) !)
ms += twentySeconds + aDay;         //   86,420,000 milliseconds
--ms;                               //   86,419,999 milliseconds
ms *= 2;                            // 172,839,998 milliseconds
std::cout << ms.count() << " ms" << std::endl;
std::cout << std::chrono::nanoseconds(ms).count() << " ns" << std::endl;

Page 214-216 (6.5.2): 2013-04-14
Jonathan Wakely told me a new trick in C++11: If an algorithm requires the call of a default constructor as end of a range, you can simply pass an empty initializer list, because the type is deduced then from the argument passed as begin of the range. Thus, on page 214 before paragraph "6.5.3 Reverse Iterators", you can insert:

Note that since C++11, you can pass empty curly braces instead of a default constructed stream iterator as the end of the range. This works because the type of the argument that defines the end of the range is deduced from the previous argument that defines the begin of the range:

copy (istream_iterator<string>(cin), // start of source
      {},                            // end of source (default constructed istream iterator)
      back_inserter(coll));          // destination

Page 249 (6.12.2): 2013-04-22
Vectors and deques provide the strong guarantee for push_back(), push_front(), emplace_back(), and emplace_front(). However to be able to do that, you either have to guarantee that move constructors of elements do not throw or copy construction is used. Thus:
    s/
All array-based containers (arrays, vectors, and deques)/All array-based containers with dynamic size (vectors and deques)/
and in the middle of this paragraph replace:

However, push and pop operations that operate at the end do not require that existing elements
get copied. If they throw, it is guaranteed that they have no effect. Furthermore, if elements have a type with copy operations (copy constructor and assignment operator) that do not throw, every container operation for these elements either succeeds or has no effect.

by:

Nevertheless, push and pop operations that operate at the (open) end give the stronger guarantee. If they throw, it is guaranteed that they have no effect. Note however, that to ensure this behavior, copy constructors instead of move constructors are used for reallocation if move constructors do not guarantee not to throw. Thus, providing a nothrow/noexcept specification for the move operations of the elements will lead to better performance. Furthermore, if elements have a type with copy and move operations (constructors and assignment operators) that do not throw, every container operation for these elements either succeeds or has no effect.

Page 263/264 (7.2.2): 2013-01-07
First paragraph: replace "these constructors are only implicitly defined" by "these operations are only implicitly defined".
In table 7.4:

Page 279 (7.3.4): 2012-04-22
Replace:

  1. If an element gets inserted with push_back() and an exception occurs, this function has no effect.
  2. insert(), emplace(), emplace_back(), and push_back() either succeed or have no effect, provided that the copy/move operations (constructors and assignment operators) of the elements do not throw.

by:

  1. push_back() or emplace_back() either succeed or have no effect. Note however, that to ensure this behavior, copy constructors instead of move constructors are used for reallocation if move constructors do not guarantee not to throw. Thus, providing a nothrow/noexcept specification for the move operations of the elements will lead to better performance.
  2. insert(), emplace(), and push_back() either succeed or have no effect, provided that the copy/move operations (constructors and assignment operators) of the elements do not throw.

Page 288 (7.4.3): 2012-04-22
Replace:

In principle, deques provide the same support for exception handing that vectors do (see Section 7.3.4, page 278). The additional operations push_front() and pop_front() behave according to push_back() and pop_back(), respectively. Thus, the C++ standard library provides the following behavior:

by:

In principle, deques provide the same support for exception handing that vectors do (see Section 7.3.4, page 278). The additional operations push_front(), emplace_front(), and pop_front() behave according to push_back(), emplace_back(), and pop_back(), respectively. Thus, the C++ standard library provides the following behavior:

Pages 277, 287, 295, 306, 322, 340, 371 (Tables 7.14, 7.18, 7.24, 7.32, 7.39, 7.45, 7.54): 2012
Emplace functions do not copy element. Instead, they initialize elements by the passed arguments. So in the tables of these pages, fix the text for emplace(), emplace_front(), emplace_back(), emplace_after(), and emplace_hint() as follows:
  Replace "Inserts a copy of an element ..." by "Inserts a new element ..." and
  replace "Appends a copy of an element ..." by "Appends a new element ...".

Page 304 Table 7.31 (7.6.2): 2013-01-07
Four times: s/Returns a ... bidirectional iterator for .../Returns a ... forward iterator for .../

Page 340/342 (7.8.2): 2013-04-14
You can also insert elements into a map with emplace() as long as key and value require only one value for initialization.
Thus,
on page 340 replace:
    Since C++11, the most convenient way to insert elements is to pass them as an initializer list, where the first entry is the key and the second entry is the value:
    std::map<std::string,float> coll;
    ...
    coll.insert({"otto",22.3});

by:
    Since C++11, the most convenient way to insert elements is to use emplace() or to pass them to insert() as an initializer list, where the first entry is the key and the second entry is the value:
    std::map<std::string,float> coll;
    ...
    coll.emplace("jim",17.7);   // see below, if key/value need more args for initialization
    coll.insert({"otto",22.3});
And on page 342 replace:
    When using emplace() to insert a new element by passing the values for its construction, you have to pass two lists of arguments: one for the key and one for the element.
by:
    When using emplace() and the key and/or the element value require more than one values for initialization, you have to pass two tuples of arguments: one for the key and one for the value.

Page 356 (7.9) for unordered_map and unordered_multimap: 2013-01-07
     s/
typename Hash = hash<T>/typename Hash = hash<Key>/
    
s/typename EqPred = equal_to<T>/typename EqPred = equal_to<Key>/

Page 370/371 (7.9.3) Inserting and Removing: 2013-01-07
You might add:

Note again that erase() operations never cause rehashing so that it is guaranteed that iterators, references, and pointers to other elements remain valid.

Page 372/373 (7.9.3): 2013-04-14
You can also insert elements into an unordered map with emplace() as long as key and value require only one value for initialization.
Thus,
on page 372 replace:
    Since C++11, the most convenient way to insert elements is to pass them as an initializer list, where the first entry is the key and the second entry is the value:
    std::unordered_map<std::string,float> coll;
    ...
    coll.insert({"otto",22.3});

by:
    Since C++11, the most convenient way to insert elements is to use emplace() or to pass them to insert() as an initializer list, where the first entry is the key and the second entry is the value:
    std::unordered_map<std::string,float> coll;
    ...
    coll.emplace("jim",17.7);   // see below, if key/value need more args for initialization
    coll.insert({"otto",22.3});
And on page 373 replace:
    Note again that when using emplace() to insert a new element by passing the values for its construction, you have to pass two lists of arguments: one for the key and one for the element.
by:
    Note again that when using emplace() and the key and/or the element value require more than one values for initialization, you have to pass two tuples of arguments: one for the key and one for the value.

Page 404,406 (8.3.3): 2013-01-07
For unordered containers, count() and equal_range() have constant complexity provided that a good hashing function is used. Thus,
replace:

Complexity: logarithmic.

by:

Complexity: logarithmic for associative containers and constant for unordered containers, provided that a good hash function is used.

Page 413-417 (8.7.1,8.7.2): 2013-01-11
For insert(pos,value), emplace(pos,args), insert(pos,initlist), insert(pos,num.value), and insert(pos,beg,end), fix the bullets covering the invalidation policy for vectors and deques as follows:

For push_front(value) and emplace_front(args), fix the bullet covering the invalidation policy for deques as follows:

For push_back(value) and emplace_back(args), fix the bullets covering the invalidation policy for vectors and deques as follows:

Page 414-417 (8.7.1): 2013-01-11
For push_back(value) and emplace_back(args), fix the bullets covering the exception safety guarantee as follows:

Page 418/419 (8.7.3): 2013-03-05
For erase(pos) and erase(beg,end), fix the first sentence of the bullets covering the exception safety guarantee by the following two sentences:

Pages 421/422 (8.8.1): 2013-07-14
In all descriptions of the splice() functions (three times), replace "insert it/them at the position" by "insert it/them before the position".

Pages 478-481 fo/sequence1.cpp and fo/sequence2.cpp (10.1.2): 2012
As the output of the programs indicate, the function object IntSequence does not generate a sequence starting with the passed initial value. Instead it returns "++value" so that the first value generated it "initialValue+1." Thus:

Page 512,514,1063 (11.2.2): 2013-01-07
Since C++11, sort() is guaranteed to have a complexity of n*log(n) in any case, which is caused by the fact that C++11 usually is implemented by using introsort (see the discussion on page 514). So the recommendation to use partial_sort() or stable_sort() to avoid the worse case behavior is no longer valid.

Thus, on page 512 replace (removed stuff in blue)

by (new stuff in red)

On page 514 in the first paragraph starting with "Now you have a brief idea" replace:

For example, the sort() algorithm in the SGI implementation of the STL is implemented by using introsort.
Introsort is a new algorithm that, by default, operates like quicksort but switches to heapsort when it is going to have quadratic complexity.

by

For example, the sort() algorithm initially was implemented by using quicksort. For this reason C++98 specified "n*log(n) on average" complexity, because quicksort can become quadratic in the worst case. However, even implementations of C++98 and C++03 switched to introsort to benefit from this new sorting algorithm, so that with C++11 the "on average" restriction was removed.

And in the index on page 1063 let "introsort" refer to page 512 rather than to page 514.

Page 533 (11.5.3): 2013-04-14
In the description of search_n() replace:
"However, the algorithm requires a unary predicate, which gets the value passed as fourth argument to search_n() as second parameter."
by:
"However, the algorithm requires a binary predicate, which gets the value passed as fourth argument to search_n() as second parameter."

Page 552 (11.5.5): 2013-04-21
In the description for is_partitioned() and partition_point() all predicates have to tbe unary predicates.
Thus, in the declaration of partition_point(), replace "BinaryPrediacte" by "UnaryPredicate" and
replace:

by:

Page 568/569 (11.6.5): 2012
As written in the description, since C++11, fill_n() and generate_n() have a return value.
Thus, on page 568 replace
    void
    fill_n (OutputIterator beg, Size num,
            
const T& newValue)
by
    OutputIterator
    fill_n (OutputIterator beg, Size num,
            
const T& newValue)
and on page 569 replace
    void
    generate_n (OutputIterator beg, Size num,
                Func op)

by
    OutputIterator
    generate_n (OutputIterator beg, Size num,
                Func op)

Page 596/597 (11.9.1): 2012
Since C++11, sort() is guaranteed to have a complexity of n*log(n) in any case, which is caused by the fact that C++11 usually is implemented by using introsort (see the discussion on page 514). Thus:

On page 596, last bullet, replace
    sort() guarantees a good performance (n-log-n) on average. However, if avoiding the worst-case performance is important, you should use partial_sort() or stable_sort().
by
    sort() guarantees a good performance (n-log-n). However, before C++11, this was only guaranteed "on average.'' So, if avoiding a worse complexity was important,
you had to use partial_sort() or stable_sort().

On page 597, bullet "Complexity:", replace
    - For sort(): n-log-n on average (aproximately numElems*log(numElems) comparisons on average).
by
    - For sort(): n-log-n (aproximately numElems*log(numElems) comparisons). Before C++11, the guarantee was: n-log-n on average.

Page 692 (13.2.17 bottom): 2012
Strike the sentence:
    "For example, strings are often implemented by using reference counting; vectors never are."
because since C++11 reference counting is no longer allowed for strings to support multithreading (as 13.2.16 states).

Page 708/709 (13.3.8): 2013-04-14
In all the declarations of rfind(), replace idx by maxIdx and 4 times in the descriptions replace "starting at index idx" by "starting at index idx/maxIdx".

Page 710/711 (13.3.8): 2013-04-14
In all the descriptions of find_last_of() and find_last_not_of(), replace idx by maxIdx and 4 times replace "starting at index idx" by "searching backward starting at index maxIdx".

Page 713 (13.3.11): 2012
The return types of the functions to convert strings to a numeric value should have the corresponding return type. In addition, the conversions to floating-point values don't have the base argument. Thus, the correct declarations are as follows:
  int stoi (const string& str, size_t* idxRet = nullptr, int base = 10)
  long stol (const string& str, size_t* idxRet = nullptr, int base = 10)
  unsigned long stoul (const string& str, size_t* idxRet = nullptr, int base = 10)
  long long stoll (const string& str, size_t* idxRet = nullptr, int base = 10)
  unsigned long long stoull (const string& str, size_t* idxRet = nullptr, int base = 10)
  float stof (const string& str, size_t* idxRet = nullptr)
  double stod (const string& str, size_t* idxRet = nullptr)
  long double stold (const string& str, size_t* idxRet = nullptr)

Page 755-757, 1058 (io/timemanipulator1.cpp): 2012
The usage of the get_time() manipulator is wrong. Instead of a raw pointer you have to pass the address of an existing tm structure. So the code on page 757 should be as follows:
    tm date;
    cout << "new date: ";

    cin >> get_time(&date, "%x");

In addition, header <ctime> is missing to declare localtime().

There are more updates in io/timemanipulator1.cpp now to make this example even more useful (because of them, the index entry for from_time_t() could also refer to page 757, now).

Page 897 bottom (16.4.4 Character Encoding Conversion): 2012
Since C++11, the C++ standard library also requires two additional standard conversions with codecvt<>:

  1. The specialization codecvt<char16_t, char, mbstate_t> converts between the UTF-16 and UTF-8 encoding schemes.
  2. The specialization codecvt <char32_t, char, mbstate_t> converts between the UTF-32 and UTF-8 encoding schemes.

As a consequence, these functions are now more useful than I wrote on top of page 898. But I have to find out details, because I am not an expert in this area of the standard.

Page 913 (17.1.2, Figure 17.1): 2013-04-21
ranlux24 and ranlux48 use the discard_block_engine adapter instead of the independent_bits_engine adapter. Thus, update Figure 17.1 accordingly.

Page 927 (17.2.2): 2013-07-13
In example complex2.cpp, for EOF you have to include <cstdio>.

Page 980 (18.3.6): 2013-01-07
For class thread, the swap() operations are missing. So in Table 18.4 add:
    | t1.swap(t2) | Swaps the state of t1 and t2 |
    | swap(t1,t2) | Swaps the state of t1 and t2 |

Page 1024 (19.1): 2013-01-07
s/
You can check whether two allocators use the same memory model by using .../You can check whether two allocators use the same memory resource by using .../
s/
If it returns true,/If operator == returns true,/

Page 1027-1030 (19.3): 2013-01-11
Since C++11, code that uses allocators should always use them via allocator traits. This also means that uninitialized_fill_n() and uninitialized_copy() cannot be used. For this reason, the following changes are necessary on these pages:

After the declaration of class vector<>, add:

Note that strictly speaking the type of elems has to be as follows, since C++11:

allocator_traits<Allocator>::pointer elems;

As for iterator traits (see Section 9.5, page 467), allocator traits were introduced to serve as common interface for generic code dealing with allocators.
They provide types such as pointer and operations such as allocate(), construct(), destroy(), and deallocate().

On page 1027, in the first implementation of vector::vector(num,val,a), substitute:

s/elems = alloc.allocate(num);/elems = allocator_traits<Allocator>::allocate(alloc, num);/
s/
alloc.construct(&elems[i],val);/allocator_traits<Allocator>::construct(alloc, &elems[i], val);/

an add:

Note that this code is still not complete because the handling of exceptions is missing.
In a proper implementation, if the construction of any element fails, all the allocated memory must be freed.

On page 1028, after the second implementation of vector::vector(num,val,a), add:

Since C++11, however, uninitialized_fill_n() and uninitialized_copy() cannot be used, because they do not use the allocator traits to construct the elements. Without allocator traits, memory management might be broken by user-defined code that specializes allocator properties and/or allocator types such that the actual call of construct() may do additional or perhaps completely different operations.

In vector::reserve(), substitute:

s/newmem = alloc.allocate(size);/newmem = allocator_traits<Allocator>::allocate(alloc, size);/
s/
uninitialized_copy (elems,elems+numElems,newmem);/.../
s/
alloc.destroy(&elems[i]);/allocator_traits<Allocator>::destroy(alloc, &elems[i]);/
s/
alloc.deallocate(elems,sizeElems);/allocator_traits<Allocator>::deallocate(alloc,elems,sizeElems);/

and add:

Again, this code is over-simplified:
The tricky part, copying the elements into the new memory, is missing because this code has to deal with exceptions and should call move operations instead of copy operations if possible.


Typos

Page xxiv (Ackn. 2nd Ed.): s/with incredible accurateness/with incredible accuracy/

Page xxiv (Ackn. 2nd Ed.): s/Everyone in the standardization process know/Everyone in the standardization process knows/

Page 4 middle (1.3): s/http::/www.cppstdlib.com/http://www.cppstdlib.com/

Page 30 (3.1.10): s/Because x gets copied by value/Because x gets passed by value/

Page 44 (4.3.1): s/Conceptionally, .../Conceptually, .../

Page 53 top (4.3.3): s/refers to the currently handled exception The value/refers to the currently handled exception. The value/

Page 55 comment in example (4.4): s/calls: l(77,33/calls: l(77,33)/

Page 66 middle (5.1.1): s/With the new semantic of C++11,/With the new semantics of C++11,/

Page 70 middle (5.1.2): s/To check whether a container is less than another container,/To check whether a tuple is less than another tuple,/

Page 71 (table 5.2): s/Returns whether t1 is less than TIt2/Returns whether t1 is less than t2/

Page 71 after Table 5.2 (5.1.2): s/ // modifies y/ // modifies s via y/

Page 73 "Additional Tuple Features" (5.1.2): s/The use of typle_size<> and tuple_element<> shows the following example:/The following example shows the use of tuple_size<> and tuple_element<>:/

Page 73 "Additional Tuple Features" (5.1.2): s/typename std::tuple<int,float,std::string> TupleType;/typedef std::tuple<int,float,std::string> TupleType;/

Page 74 util/printtuple.hpp (5.1.3): s/ // helper: print element with index IDX of tuple with MAX elements / // helper: print elements with index IDX and higher of tuple t having MAX elements /

Page 86 (5.2.2) twice: s/nico shared 3 times/nico is shared 3 times/ and s/name of 1st kid of nicos mom: nico/name of 1st kid of nico's mom: nico/

Page 88 (5.2.2) twice: s/nico shared 1 times/nico is shared 1 times/ and s/name of 1st kid of nicos mom: nico/name of 1st kid of nico's mom: nico/

Page 98 (5.2.5): s/making it less error prone than auto_pointers have been/making it less error prone than auto_ptrs have been/

Page 99 bottom code (5.2.5): s/create and initialize an unique_ptr/create and initialize a unique_ptr/

Page 99 bottom code (5.2.5): s/std::unique<ClassA> ptr(new ClassA);/std::unique_ptr<ClassA> ptr(new ClassA);/

Page 102 (5.2.5): s/ // OK, delete old object and own new / // OK, delete object owned by ptr and become owner of new object /

Page 103 code (5.2.5): s/(previously returned object of f() gets deleted)/(object previously returned by source() gets deleted)/

Page 103 code (5.2.5): s/destructors are called only for objects that have been fully constructed./destructors are called only for member objects that have been fully constructed./

Page 104 example with ClassB (5.2.5): s/might cause resource leak if second new throws/will cause resource leak if second new throws/

Page 106 (5.2.5): s/Conceptionally, .../Conceptually, .../

Page 110 (5.2.6): s/Class unique_ptr<> is templatized for/Class unique_ptr<> is specialized for/

Page 114 (5.2.8): s/because this also avoids resource leaks or transfers ownership./as such a class would also avoid resource leaks and be able to transfer ownership./

Page 123 code (5.4.1): s/"foo() called for value to "/"foo() called for value "/

Page 125 bottom (5.4.2): s/typedef integral_constant<T,v> type;/typedef integral_constant<T,val> type;/

Page 129 (5.4.2): s/can invoke member functions of rvalues/can invoke member functions on rvalues/

Page 129 (5.4.2): s/std::uses_allocator<> is defined in <memory<>/std::uses_allocator<> is defined in <memory>/

Page 135 (5.5.1): s/in some particular order./according to some particular sorting criterion./

Page 136 (5.5.2): s/the values are moved or move assigned ... Before C++11, the values were /the values are moved or move assigned if possible ... Before C++11, the values were always /

Page 150 util/clock.hpp (5.7.3): s/ // if time unit is less or equal one millisecond / // if time unit is less than or equal to one millisecond /

Page 154 (5.7.3): s/summertime/summer time/

Page 157 (5.7.3) s/Note, however, that these operation do not check whether a combination performs an overflow/Note, however, that these operations do not check whether whether a computation performs an overflow/

Page 159 util/timepoint.hpp (5.7.4): s/ // day of month (0 .. 31) / // day of month (1 .. 31) /

Page 166 end of 2nd bullet (6.1): s/while running over/while iterating over/

Page 166 bottom (6.1): s/arbitrary types and classes, respectively./arbitrary types and classes./

Page 171 (6.2.1): s/it would have a bad runtime for vectors/it would have a bad running time for them/

Page 171 (6.2.1): s/(an object of class array)/(an object of class array<>)/

Page 173 top (6.2.1): s/Historically, we had only one list class in C++11./Historically, we had only one list class in C++98./

Pape 173 (6.2.1): s/This is a lot worse than the amortized constant time provided by vectors and deques./This is a lot worse than the constant time provided by vectors deques, and arrays./

Page 179 (6.2.2) stl/multimap1.cpp: s/insert some elements/assign some elements/

Page 181 (6.2.3): s/According to associative containers/Analogous to associative containers/

Page 191 (6.3): s/the loop does not run, because coll.begin() would equal coll.end()/the body of the loop is never executed, because coll.begin() equals coll.end(), then/

Page 198 (6.3.2): s/(in accordance with pointer arithmetic .../(corresponding to pointer arithmetic .../

Page 229 (6.8.2 end): s/to declare sets that use this criterion for sorting its elements./to declare sets that use this criterion for sorting their elements./

Page 233 2nd paragraph (6.9): s/If you need such a state, you have declare/If you need such a state, you have to declare/

Page 233 (6.10.1) Footnote 12: s/for every object that can be used as a function call./for every object that can be used to perform a function call./

Page 251 (6.13.2): s/are therefore not provided for polymorphism/are therefore not equipped for polymorphism/

Page 254 (7.1.2): s/some containers even don't fulfill/some containers don't even fulfill/

Page 256 (7.1.2): s/or from standard input/or from an input stream/

Page 257 second bullet (7.1.2): s/You can initialize a container from standard input:/You can initialize a container from an input stream, such as standard input:/

Page 258 (7.1.2): s/which, however, are in a different container then/which, however, are in different containers then/

Page 259 bottom (7.1.2): s/for write access:/for read/write access:/

Page 260 top (7.1.2): s/for write access/for read/write access:/

Page 261 (7.2): s/Conceptionally, .../Conceptually, .../

Page 266 top (7.2.2): s/So, in doubt you must ensure/So, if in doubt, you must ensure/

Page 266 code example (7.2.2): s/ // throws out_of_range exception/ // throws out_of_range exception for array<...,4>/

Page 271 bottom (7.3.1): s/v.capacity==v.size()/v.capacity()==v.size()/

Page 271 bottom (7.3.1): s/Before C++11, there you could shrink the capacity only indirectly/Before C++11, you could only indirectly shrink the capacity/

Page 273 bottom (7.3.2): s/while removing all ordinary elements/while removing all existing elements/

Page 278 (7.3.3): s/std::vector<char,41> v; // create static array of 41 chars/std::vector<char> v; // create vector as dynamic array of chars/

Page 291 first bullet (7.5.1): s/from both end./from both ends./

Page 296 top (7.5.2): s/Because the lambda returns, whether/Because the lambda returns whether/

Page 296 top (7.5.2): s/iterators and references to other members/iterators and references to other elements/

Page 300 (7.6.1): s/Conceptionally, .../Conceptually, .../

Page 304 after Table 7.30 (7.6.2): s/to ensure that coll is not modified/to ensure that the container is not modified/

Page 307 top (7.6.2): s/The drawbacks ... gets even worse/The drawbacks ... get even worse/

Page 315 (7.7.1): s/when elements with a certain value are searched./when searching for elements with a specific value./

Page 319 (7.7.2): s/The find() member function searches the first element/The find() member function searches for the first element/

Page 324 (7.7.2): s/The fact that the return type for the insert functions with the additional position hint doesn't have the same difference as the insert functions without the position hint ensures that you have one insert function that has the same interface for all container types./The fact that all the insert functions with the additional position hint share the same return type has a good reason. It enables generic code that can insert elements to any container (except arrays and forward lists)./

Page 324 erase() example (7.7.2): s/std::set<Elem> coll;/std::multiset<Elem> coll;/

Page 336 (7.8.2): s/do_something();/do_something(pos);/

Page 337 (7.8.2): s/for (auto elem& : coll) {/for (auto& elem : coll) {/

Page 339 (7.8.2): s/It works the same way for multimaps./It works the same way for multimaps (replacing the first matching key)./

Page 350 (7.8.5): s/(in contrast to finding a key with a certain value):/(in contrast to finding an element with a certain key):/

Page 355 (7.9): s/Conceptionally, .../Conceptually, .../

Page 358 after Figure 7.18 (7.9.1): s/("amortized'' because the occasional rehashing happens that occurs can be a large operation with a linear complexity)./("amortized'' because of the occasional rehashings, which can be large operations with linear complexity)./

Page 359 (7.9.1): s/You can specify a maximum load factor, which leads to automatic rehashing when it is exceeded./You can specify a maximum load factor, which leads to automatic rehashing when the number of elements in the container grows./

Page 359 (7.9.1): s/erase() never invalidates iterators, references, and pointers to the elements./erase() never invalidates iterators, references, and pointers to other elements./

Page 364 middle (7.9.2): s/can be very tricky, In addition, providing/can be very tricky. In addition, providing/

Page 366 second code example (7.9.2): s/Customer& c2/const Customer& c2/

Page 367: (7.9.3): s/Unordered containers are optimized for fast searching of elements./Unordered containers are optimized for fast searching of elements with a specific value (unordered sets and multisets) or key (unordered maps and multimaps)./

Page 368: (Table 7.51): s/with value val/with key/value val/ (twice)
and s/
with a value equal to val/with a key/value equal to val/

Page 369 (7.9.3): s/for (auto elem& : coll) {/for (auto& elem : coll) {/

Page 370 (7.9.3) twice: s/pair<const std::string,int>/std::pair<const std::string,int>/

Page 370 (7.9.3): s/unordered_map<std::string,int>::value_type/std::unordered_map<std::string,int>::value_type/

Page 371 Table 7.54 (7.9.3) twice: s/and, for unordered containers, whether it succeeded/and, for unordered_sets and unordered_maps, whether it succeeded/

Page 378 (cont/hashfunc1.cpp): s/Customer& c2/const Customer& c2/

Page 380 (cont/hashfunc2.cpp): s/Customer& c2/const Customer& c2/

Page 393 Table 7.57 (7.12): s/Inserting/removing references, pointers/Inserting/removing invalidates refs/ptrs/

Page 397 (8.0) 1st paragraph: s/and string.         In the following sections/and string. In the following sections/ (space removed)

Page 404 (8.3.3) add: For unordered containers, the member functions even have constant complexity if a good hashing function is used.

Page 404 (8.8.3) count(): s/Complexity: logarithmic./Complexity: logarithmic for associative containers and constant for unordered containers, provided that a good hash function is used./

Page 406 (8.8.3) equal_range(): s/Complexity: logarithmic./Complexity: logarithmic for associative containers and constant for unordered containers, provided that a good hash function is used./

Page 412 fifth bullet (8.7.1) container::insert(value): s/(unordered) sets and maps have the second and fourth signature/(unordered) sets and maps have the third and fourth signatures/

Page 421 (8.8.1) splice(pos,source): s/Thus, they belong to this afterward./Thus, they refer to elements in this afterward./

Page 422 (8.8.1) splice(pos,source,sourcePos): s/Thus, they belong to this afterward./However, for the spliced element, they refer to an element in this afterward./

Page 422 (8.8.1) splice(pos,source,sourceBeg,sourceEnd): s/Thus, they belong to this afterward./However, for the spliced elements, they refer to elements in this afterward./

Page 425 (8.8.2) erase_after(beg,end): In first bullet, remove: "[beg,end)." before "For example:"

Page 425 (8.8.2) erase_after(beg,end): s/coll.erase(coll.before_begin(),coll.end());/coll.erase_after(coll.before_begin(),coll.end());/

Page 425 (8.8.2) splice_after(pos,source): s/Thus, they belong to this afterward./Thus, they refer to elements in this afterward./

Page 426 (8.8.2) splice_after(pos,source,sourcePos): s/Thus, they belong to this afterward./However, for the spliced element, they refer to an element in this afterward./

Page 426 (8.8.2) splice_after(pos,source,sourceBeg,sourceEnd): s/Thus, they belong to this afterward./However, for the spliced elements, they refer to elements in this afterward./

Page 431 (8.10.2): s/const KeyEqual& eqPred const Allocator& alloc/const KeyEqual& eqPred, const Allocator& alloc/

Page 432 fourth bullet (8.10.2): s/and hat uses/and that uses/

Page 433 (9.1): s/and their type, you should/and their types, you should/

Page 433 (9.2): s/the runtime would be poor/the performance would be poor/

Page 437 (9.2.3): s/Class <forward_list<>/Class forward_list<>/

Page 446 (9.3.3): s/you don't recognize that the performance is getting worse/you might not recognize that the performance gets worse/

Page 446 (9.3.3): s/To process the difference/To compute the difference/

Page 446 (9.3.3): s/have to process the distance ... and process the difference of/have to obtain the distance ... and compute the difference of/

Page 448 (9.4.1): s/According to begin() and end()/As with begin() and end()/

Page 458 (9.4.2): s/A general inserter is available for all standard containers except for arrays and forward lists,/A general inserter is usable for all standard containers (except for arrays and forward lists)/

Page 489 (10.2.2): s/In the same way, you can define a binder that represents a sorting criterion./In the same way, you can define a binder that represents a search criterion./

Page 494 (10.2.2): s/Thus, mem_fn() simply calls an initialized member function for a passed argument while.../Thus, for the object returned by mem_fn(...), operator () simply calls the member function it was initialized with. The function call is performed for the object passed as first argument while.../

Page 504 (10.3.4): s/Person& p2/const Person& p2/

Page 597 (11.9.1): s/log(numElems)2/(log(numElems))2/

Page 633 (12.1.1): s/• top() returns the next element in the stack./• top() returns the next available element in the stack./

Page 639 (12.2.1): s/• front() returns the next element in the queue/• front() returns the next available element in the queue/

Page 639 (12.2.1): s/• back() returns the last element in the queue/• back() returns the last available element in the queue/

Page 643 (12.3.1): s/• top() returns the next element in the priority queue./• top() returns the next available element in the priority queue./

Page 648 (12.4.4) top() and front(): s/• All forms, if provided, return the next element./• All forms, if provided, return the next available element./

Page 653 (12.5.1) footnote 1: s/unsigned long was not provided/unsigned long long was not provided/

Page 653 (12.5.1) footnote 1: s/to_ulong() is still callable if/to_ulong() is still callable and works fine if/

Page 671 (13.2.6): s/cs[2]; // yields 'i' as const char&/cs[2]; // yields 'c' as const char&/

Page 686 (13.2.14): s/The transformation is specified as a lambda/The transformation is specified with a lambda/

Page 726 (14.2): s/which means "all but character < any times."/which means "all but character > any times."/

Page 902 (16.4.4) in i18n/wstring2utf8.cpp twice: s/ISO Latin-15 encoding/ISO Latin-9 encoding/

Page 954 first bullet (18.1.1): s/both function return immediately/both functions return immediately/

Page 955 (18.1.1) twice: s/while (f.wait_for(chrono::seconds(0) != future_status::ready)) {/while (f.wait_for(chrono::seconds(0)) != future_status::ready) {/

Page 969 (18.2.2) in concurrency/promise1.cpp: s/read character and throw exceptiopn if 'x'/read character and throw exception if 'x'/

Page 973 (18.3): s/Conceptionally, .../Conceptually, .../

Page 989 (18.5.1): s/but can't conceptionally .../but can't conceptually .../

Page 1058: s/from_time_t()/from_time_t() 757/

Page 1063: s/introsort 514/introsort 512/


Home of the C++ Library book, 2nd edition