Nicolai M. Josuttis: solutions in time  C++ Templates: Errata for the 2nd to 4th Printings

C++ Templates - The Complete Guide

Errata for the 2nd to 4th Printings
Jul 24, 2004

This is the errata of the 2nd and the following printings of the book C++ Templates by David Vandevoorde and Nicolai M. Josuttis. It covers all errors that were found until the 4th printing came out. Thus, you will find additional errors in the erratas for the following editions.
The errata is organized in the following way:
- The first part lists technical errors
- The second part lists typos (including stylistic changes due to consistency etc.)


Errors

Page 21: s/in Section 7.3 on page 89/in Chapter 6/

Page 26, Section 3.2:
Replace:
    You can use a type of an instantiated class template as any other type, as long as the operations are supported:

by the following:
    An instantiated class template's type can be used just like any other type. You can qualify it with const or volatile, or derive array and reference types from it. You can even use it as a type parameter when building another template type:

Page 39, Section 4.2:
The sentence "addValue<int, 5> is a function template, and function templates are ..." is a bit sloppy. More exactly, it has to be "addValue<int, 5> is a function template instance, and function template instances are ...".

Page 47 (stack5assign.hpp),
Page 49 (stack6assign.hpp),
Page 54 (stack8.hpp):
In the templified assignment operator of Stack the test of assignment to itself is useless because the template member assignment operator is never used for assignment between objects of the same type, and if the address of rhs == this, then the object must reasonably be of the same type.

Page 69, Section 6.3.1:
Replace
  export inline T const& max (T const&a, T const& b)
  {                              // ERROR: both export and inline
      return a < b ? b : a;
  }

by the following:
  export template<typename T>    // ERROR: both export and inline
  inline T const& max (T const& a, T const& b)
  {                           
      return a < b ? b : a;
  }

Page 110:
After the beginning of the class declaration
    class X {
you have to insert public:, so the the following members are accessible.

Page 111:
After the beginning of the class declaration
    class Base {
you have to insert public:, so the the following members are accessible.

Page 151, Section 10.3.4
Replace
At this point, dependent qualified names are looked up using both ordinary and argument-dependent lookup rules.
by:
At this point, dependent qualified names are looked up using ordinary lookup rules (because argument-dependent lookup only applies to certain unqualified names).

Page 130: s/void boom(Trap<void>& bomb)/void boom(Victim<void>& bomb)/

Page 130: s/the generic X<T>::x/the generic Trap<T>::x/

Page 172, Section 11.3:
The example code of class S has to be as follows:
  class S {
    public:
      template<typename T, int N> operator T&();
  };
and the corresponding text at the end of Section 11.3 has to be the following, then:
Here we are attempting to convert S to int (&)[20]. Type A is therefore int[20] and type P is T. The deduction succeeds with T substituted with int[20].

Page 208:
Twice, substitute:
    MyInt = count<MyInt>(c);
    assert(MyInt == i);

by the following:
    MyInt j = count<MyInt>(c);
    assert(j == i);

Page 210:
The const at the end of the declarations of the static functions Bracket::address() and Bracket::bytes() are wrong. Therefore, you have to remove const four times.

Page 305ff, Sections 17.3 and 17.4
The current implementations of Sqrt<> don't handle 0 as argument. There is no problem to handle it by defining the minimum/starting value as 0 instead of 1. However, a lot of modifications are necessary then. The most obvious ones are the following:
 Page 305, sqrt1.hpp: s/int LO=1/int LO=0/
 Page 305: s/the square root is at least one/the square root is at least zero/
 Page 308, sqrt2.hpp: s/int LO=1/int LO=0/
 Page 310: s/for (I=1;/for (I=0;/
 Page 310, sqrt3.hpp: s/int I=1/int I=0/
 Page 311, sqrt4.hpp: s/int I=1/int I=0/
However, the expansions discussed with this example change accordingly, which means that the whole contents of this section has to be rewritten in some way. Therefore, we will keep the contents of the book as it is.

Page 318, Section 17.7:
to be exact, for the instantiation process of dot_product<3>(a,b) some parentheses are missing to reflect the fact that the
additions are done starting at the end of the array. So the expression becomes:
  
DotProduct<3,int>::result(a,b)
   = *a * *b + DotProduct<2,int>::result(a+1,b+1)
   = *a * *b + (*(a+1) * *(b+1) + DotProduct<1,int>::result(a+2,b+2))
   = *a * *b + (*(a+1) * *(b+1) + *(a+2) * *(b+2))

Page 339, Section 18.2.5
the code at the bottom of the page (which is exprtmpl/exprops4.hpp) must be replaced by:
  template<typename T, typename R>
    template<typename T2, typename R2> inline
  Array<T, A_Subscript<T, R, R2> >
  Array<T, R>::operator[](Array<T2, R2> const& b) {
      return Array<T, A_Subscript<T, R, R2> >
             (A_Subscript<T, R, R2>(*this, b));
  }

Page 350ff, Section 19.2
We need additional partial specializations of CompoundT for const and volatile pointer variants. Thus, for the sentence at the bottom of page 350 introducing types/type3.hpp, add the following footnote:

The definitions of CompoundT<T* const>, CompoundT<T* volatile>, and CompoundT<T* const volatile> are omitted for brevity. They are identical to the definition of CompoundT<T*>.

Page 391, Section 20.2.8:
When declaring a friend class template the keyword friend has to follow the template parameters. Thus, replace:

    friend template<typename T2, typename CP2, typename OP2>
    class CountingPtr;

by the following:
    template<typename T2, typename CP2, typename OP2>
    friend class CountingPtr;

Page 412, Section 21.3:
Figure 21.1 is slightly incorrect. In the middle two boxes, the second type has to be Tuple<...>::BaseT. Thus, insert ::BaseT before the final closing >.


Typos

Page 15: s/return max (max(a,b), c);/return ::max (::max(a,b), c);/
Page 16: s/max/::max/
(5 times in cited rows of the listing before)

Page 24: s/Because the vectors back()/Because back()/

Page 27: s/a type definition does define/a type definition defines/

Page 32: s/mange/manage/

Page 37: s/throw "Stack<>::push(): stack is full";/throw std::out_of_range("Stack<>::push(): stack is full");/

Page 41: s/and objects with internal linkage/and pointers to objects with internal linkage/

Page 48: s/therefore pop() still returns a float/therefore top() still returns a float/

Page 49: s/std::cout << vStack.pop()/std::cout << vStack.top()/

Page 50: s/stack<int,std::vector>/Stack<int,std::vector>/

Page 59: s/no general solutions/no general solution/

Page 65, 67: s/template std::string Stack<std::string>::top();/template std::string Stack<std::string>::top() const;/

Page 82: s/to track the pattern or/to track the pattern of/

Page 89: s/initializations and a missing/initializations as well as a missing/

Page 99: s/invalid: /ERROR: /

Page 107: s/return *P/return *P;/

Page 113: s/However, this is less prone to problems because unlike copy constructors, assignment operators are never called implicitly./However, this is less prone to problems because implicit calls of copy-assignment operators are less common./

Page 115: s/multiply( void*)/multiply(void*)/

Page 119: s/to identify to which entity is being referred./to identify the entity being referred./

Page 119: s/provide tables Table/provide Table/

Page 120: s/Used to denote user-defined/Used to denote a user-defined/

Page 121: s/can be easily found/can be found easily/

Page 121: s/then base classes may also be looked up/then base classes may also be searched/

Page 123: Make "For class members" a separate bullet.

Page 127: s/initializating/initializing/

Page 127: s/context-free language/context-free languages/

Page 129: s/the "larger than" symbol/the "greater than" symbol/

Page 135: s/Conversely, we cannot ... until we have/Furthermore, a compiler cannot ... until it has/

Page 142: s/class template definition must seen/class template definition must be seen/

Page 143: s/now arises How much/now arises: How much/

Page 145: s/subsituted/substituted/

Page 148: s/declaration of definition/declaration or definition/

Page 152: s/of main() function/of main()/

Page 171: s/void fppm(void (X<N>::*p)(X<N>::I));/void fppm(void (X<N>::*p)(typename X<N>::I));/

Page 172: s/class B<T> {/class B {/

Page 181: s/int x, y;/int x=42, y=-7;/

Page 193: s/enum { max= 10; };/enum { max = 10 };/

Page 194: s/enum { max= 100; };/enum { max = 100 };/

Page 198: s/the generic ones at points (4) and (5)/the generic ones at points (5) and (6)/

Page 199: s/T sm;/static T sm;/

Page 199: s/enum { count = 1; };/enum { count = 1 };/

Page 200: s/enum { count = 2; };/enum { count = 2 };/

Page 203: s/on other hand/on the other hand/

Page 210: s/static double convert (double val) const {/static double convert (double val)/

Page 212: s/typedef list<T> MyList;/typedef std::list<T> MyList;/

Page 219: s/core() is instantiated with type int/clear() is instantiated with type int/

Page 224: s/enum { n_bytes; };/enum { n_bytes };/

Page 224: s/enum { max = ... ::max; }/enum { max = ... ::max };/

Page 226: s/Chapter 17/Chapter 18/

Page 241: s/Iterator's operations/Iterator operations/

Page 244: s/long-term potential evolutions almost always pays off./long-term, potential evolutions almost always pay off./

Page 247: s/all letters in the word template/all letters in the word templates/

Page 272: s/of two type parmeters:/of two type parameters:/

Page 274: s/the IsFundaT and IsEnumT templates/the IsFundaT and IsEnumT templates (see Chapter 19)/

Page 278: s/more mess/messier/

Page 280: s/bitwised copied/bitwise-copied/

Page 280: s/copy (typename RParam<T>::ResultT src,/copy (typename RParam<T>::Type src,/
Page 281: s/
copy_init (typename RParam<T>::ResultT src,/copy_init (typename RParam<T>::Type src,/

Page 281: s/::new((void*)((char*)dst+k)) T(src[k]);/::new((void*)((T*)dst+k)) T(src[k]);/
Page 282: s/::new((void*)((char*)dst+k)) T(src[k]);/::new((void*)((T*)dst+k)) T(src[k]);/

Page 283: s/(void*)src, n);/(void*)src, n*sizeof(T));/ (four times)

Page 292: s/empty class After all/empty class. After all/

Page 296/297: s/ObjectCounter<CountedType>::count;/count;/ (four times inside member functions)

Page 305: s/Lets/Let's/

Page 307: s/result of computation/result of a computation/

Page 313: s/The are a few/There are a few/

Page 315: s/for serious high-performance applications/for high-performance applications/

Page 320: s/to the metaprogramming/to metaprogramming/

Page 321: s/for small, fixed-size array/for small fixed-size arrays/

Page 334: s/value we need/value, we need/

Page 339(2nd but last line): s/a.rep(),b.rep()/this->rep(),b.rep()/

Page 341: s/CopierBase<T>/CopierInterface<T>/ (twice)

Page 342: s/template<typename R>/template<typename Rep>/
        
s/double foo(Array<double, R> const&);/double foo(Array<double, Rep> const&);/

Page 357, types/type7.hpp: s/conversion to function types/conversion to function and array types/

Page 358 (2nd bullet): s/that takes type T as its second argument/that takes type T as its argument/

Page 369: s/swap/std::swap/ (twice)

Page 376: s/may trigger an exception that occurs/may trigger an exception/

Page 386: s/for that fact that/for the fact that/

Page 388: s/the type of the pointer/the type of the counter/

Page 390: s/a int const*/an int const*/

Page 390: s/assume cp is an counting pointer/assume cp is a counting pointer/

Page 392: s/class BoolConversionSupport {/struct BoolConversionSupport {/

Page 393: s/operator BoolConversionSupport::*() const {/operator int BoolConversionSupport::*() const {/

Page 393: s/return cp == p;/return cp.operator->() == p;/
Page 393: s/
return p == cp;/return p == cp.operator->();/

Page 397: s/might looks as follows/might look as follows/

Page 410: s/is convenient to apply/makes it convenient to apply/

Page 424: s/void B1::mf2()/void B2::mf2()/

Page 443: s/typename ForwardParamT<P2>::Type a3/typename ForwardParamT<P3>::Type a3/

Page 447 functors/compose1.cpp: s/Composer<Abs,Sine>(Abs(),Sine())(0.5) /Composer<Abs,Sine>(Abs(),Sine())(-0.5)/

Page 448 functors/compose2.cpp: s/Compose(Abs(),Sine())(0.5)/Compose(Abs(),Sine())(-0.5)/

Page 448: s/member functors first and second/member functors fo1 and fo2/

Page 453 functors/compose5.cpp: s/compose(Abs<double>(),Sine<double>())(0.5)/compose(Abs<double>(),Sine<double>())(-0.5)/

Page 457 functors/min.hpp: s/return a<b ? b : a;/return a<b ? a : b;/

Page 465: s/repeating v1 and v4/repeating v1 and v3/

Page 478: s/(essentially, entities declared in an unnamed namespace scope or in the global scope using the static specifier)/(essentially, entities declared with the static specifier in the global scope or in a namespace scope)/

Page 479: s/the typeid operator ends designating/the typeid operator ends up designating/

Page 490: s/initialization of str2/assignment to str2/

Page 495: s/Furthermore, if viable functions to different classes related by inheritance exist, a conversion to the most derived one is preferred./Furthermore, if conversions to different classes related by inheritance exist, a conversion to the most derived class is preferred./

Page 496: s/the "closest one"/the "closest base"/

Page 496: s/operator()(double, double);/void operator()(double, double) const;/


Home of the C++ Templates book