Practical Solutions for Real-Life Programming

Home Reviews Errata Links Contact

Errata

Updated: 25th February 2007
This section is comprised of any changes or concerns related to Imperfect C++ since its publishing. You can find listed missing material (from the CD), enhancements to the book's content, code errata / bug reports, typos, and other related information. Click through to Amazon.com
Date Author Section Details Type
23rd March 2005 Serge Krynine Bibliography

Instead of:
  "[Vand2003]. The Comprehensive Guide ..."
it should read:
  "[Vand2003]. The Complete Guide ..."

Typo
4th May 2005 Ike Naar page xxix

In the definition of 'value type' on page xxix, it is said that "Equality (and inequality) is reflexive, symmetric, and transitive". Inequality is not reflexive or transitive.

Erratum
28th December 2006 Thomas Schell page 8; section 1.2.4

The definition of must_be_pod is missing the preceeding template <typename T>

Erratum
26th May 2005 Mark Hoebeke page 19; section 1.4

There are two ? tokens, when there should only be one:

  # define assert(x) ((!x) ?

    ? assert_function(#x,__FILE__,__LINE__)

    : ((void)0))

Typo
21st April 2005 Pablo Aguilar page 21; section 1.4.2

Instead of:
  "... experience a memory system during debugging ..."
it should read:
  "... experience a memory exception during debugging ..."

Typo
28th February 2005 Markus Elfring page 41; section 3.2.1

The statement
  pthread_mutex_lock(&service.unlock);
should read
  pthread_mutex_unlock(service.lock);

Typo
21st April 2005 Pablo Aguilar page 45; listing 3.4

The statement
  return OnParseSymbol();
should read
  return cw.OnParseSymbol();

Typo
11th April 2005 Serge Krynine page 47; section 3.4.1

The statement
  int *&device = dc.m_file;
Should read:
  int *&device = dc.m_device;

Erratum
8th August 2005 Martin Moene page 52; listing 3.9

The MIL of mem_buffer is:

  mem_buffer(size_t size)
    : m_size(cb)
    , m_buffer(. . .)

should read:

  mem_buffer(size_t size)
    : m_size(size)
    , m_buffer(. . .)

Typo
28th February 2005 Markus Elfring page 57; section 4.3

There is a semi-colon missing from the line str2.Empty();

Typo
30th April 2005 Martin Boucher page 77; listing 6.5

Types of m_var and m_revert were defined in terms of V, when they should be in terms of T.

  template< typename T >
  class ValueScope
  {
    ...

  private:
    T &m_var;
    T m_revert;
  };

Typo
23rd March 2005 Jonathan Small page 112

I'm a little way through your new book, and have to say I think its pretty good. Just a quick comment on p112 about the vtbl layout. I'm a COM veteran, so I've had a reasonable amount of experience in it.

The gcc layout is different because of the different style of 'offset correction' techniques used. That is the correction of the 'this' pointer when it gets passed to the function. gcc 2.9x and older (non MS) compilers use a technique where the offset is placed in the vtable next to the functions address. Thus when the function is called the objects pointer passed in is corrected by this offset, before the function is actually called.

In the case of VC + later gcc compilers, the technique used is function 'thunking' where a new function is created which corrects the pointer before the base classes function is called (now with the correct 'this'). The technique is known as 'vtable thunking'.

To illustrate the problem:

  struct IA
  {
    virtual void __stdcall DoA() = 0;
  };

  struct IB:public IA
  {
    virtual void __stdcall DoB() = 0;
  }

  struct CBase
    :public IA
  {
    /* override */void __stdcall DoA() { printf("CBase::DoA\n"); }
  }

  struct CDerived
    : public IB
    , public CBase
  {
    /* override */void __stdcall DoA() { printf("CDerived::DoA\n"); }
    /* override */void __stdcall DoB() { printf("CDerived::DoB\n"); }
  }

  int main(int,char *[])
  {
    CDerived der;
    IA *aptr = static_cast<CBase *>(&der);
    IA *bptr = static_cast<IB *>(&der);
  }

In this situation both aptr + bptr point to a IA interface pointer, but they are different IA interface vtables. So that a call to aptr is correctly routed to CDerived's DoA() function the 'this' pointer passed to the call is corrected so that it when its passed into CDerived's DoA() the this pointer is correctly set.

And in this case if you looked at the gcc2.9x vtable you would see different numbers for v3 and v4 (from your example) which would make this correction.

Ie in gcc it is the callers responsibility to fix up this. With VC and later compilers the callee does the fix up, through a generated/invisible 'thunking' function. This can be seen/explained via the disassembly more simply :)

Comment
11th August 2005 Martin Moene page 124; listing 9.1



  printf("%s => %s", path, find_filename(fileName));

should read:

  printf("%s => %s", fileName, ffn(fileName));

Typo
23rd March 2005 Jonathan Small page 126; section 9.2.1

It says a 'dynamic library is complete'. Jonathan says that this is "not necessarily so - you can have imports and exports within a dll - such that the dll has to have functions imported from it from the executable or another dll. I have used this on a dll system loading a device driver where the dll, had to use standard library calls, and they only worked with the standard library functions linked into the executable (as they were correctly set up prior to main). This was a while ago using Watcom/DOS but the point is the Dll standard supported imports/exports. I dunno if its used much with Win32 if at all.".

While I certainly take the point that a dynamic library may (and in fact almost always does) depend on symbols in other dynamic libraries, I'm not confident that one can depend on symbols defined inside the loading process; naturally this is a perfectly normal and well-used technique for static libraries. Certainly I'm pretty sure that one cannot do this with Win32 DLLs. I'd be interested to hear from anyone whether this is possible under UNIX/Linux.

Erratum
1st February 2005 Jon Redinger page 136; section 10.1.2

The use of the member type class_type (as described later in section 18.5.3; standing for the full type of a specialised class template, or the type of a non-template class) is premature. Each occurrence of it in this listing should instead be atomic_integer

Typo
5th November 2006 Rupert Kittinger page 138; section 10.2.2

C: I would like to comment on the spin mutex section (10.2.2). I think this class is not really "spinning" because of the call to sched_yield(). In all other implementations I have seen, a spinlock basically loops until the locking succeeds. The idea is that if the resource is only locked for a very short time, busy looping is cheaper than a context switch. So spinlocks may be very effective especially when there is a lot of contention. (Needless to say, this only makes sense on multiprocessor machines!)

A: You make a good point. I've updated the STLSoft spin_mutex class(es), so that it is now a class template - spin_mutex_base - that takes a policy class that determines whether the spin incorporates a yield or not. There are two specialisations typedef'd: spin_mutex_no_yield and spin_mutex_yield.

The spin_mutex class is now a typedef to spin_mutex_no_yield, unless STLSOFT_OLD_SPIN_MUTEX_BEHAVIOUR is #define'd, in which case it's a typedef to spin_mutex_yield.

These changes are available from STLSoft 1.9.1. beta 29 or later..

Comment
17th August 2005 Martin Moene page 139; section 10.3

"Before we and move on ..." should read "Before we move on ...".

Typo
28th February 2005 Markus Elfring page 143; section 10.3.3

"... flavous of Linux ..." should be "... flavours of Linux ..."

Typo
23rd March 2005 Jonathan Small page 152; listing 10.8

The line:

  if(NULL==value)

should read:

  if(NULL==thing)

Typo
23rd March 2005 Matthew Wilson page 152; listing 10.8

The variable declaration:

  Tss key_func(. . .);

has a typo - it's TssKey - and also looks too much like a function declaration. It's better expressed as follows:

  TssKey key_func(closeThing, . . .);

Erratum
17th August 2005 Martin Moene page 159

"Stipulating the object files for object1.cpp, object2.cpp and object3.cpp ... ..." should read "Stipulating the object files for main.cpp, object2.cpp and object3.cpp...".

Typo
17th August 2005 Martin Moene page 161

"Without the static, the linker would complain ..." should read "Were it not declared within an anoymous namespace, the linker would complain ..."

Typo
6th January 2006 Robert Dexter page 163; listing 11.5

The GetInstance() method must be defined static.

Erratum
6th January 2006 Robert Dexter page 164; listing 11.6

The GetInstance() method must be defined static.

Erratum
6th January 2006 Robert Dexter page 165; listing 11.7

The GetInstance() method must be defined static.

Erratum
8th April 2005 Phil Hodges page 173

"rationale" should be "rational" (twice)

Typo
11th January 2006 Robert Dexter page 196; listing 13.2

The variable i8 should be named si8. The variable ui64 should be declared as of type uint64_t.

Erratum
23rd June 2005 Juan Antonio Zaratiegui Vallecillo page 209; listing 14.1

I have tried some of your samples, both in Borland 5.6.4 and GCC 3.2, and there is a problem with page 209, listing 14.1, which fails unexpectedly on GCC. I had to add the next overload:

  void reject_subscript_operator(void * const)
  {}

because GCC would fail to use the function for

  reject_subscript_operator(pv);

instantiating instead the template. I don't know which of those compilers is following the Standard rules for resolution, as there is a cv-qualifier implied, and C++ standard is pretty difficult to understand in such themes. Or are we in front of unspecified/implementation-specific material?

Comment
17th September 2004 Matthew Wilson page 211; section 14.3

There's a problem with the use of the dimensionof() construct on arrays, when the type of the array is a locally defined struct/class. This is due to the restrictions on linkage of template parameterising types, as is discussed in Chapter 34.

The solution in the STLSoft libraries is pretty much a hack at this point. The stlsoft_num_elements() construct, which is equivalent to the dimensionof construct, uses a helper macro, called stlsoft_num_elements_() which implements that normal, "C", approach using sizeof(x) / sizeof(0[x]). It's hardly pretty, or unambiguous, however, so a better named macro is planned in the near future.

Erratum
25th July 2005 Dirk Bonekaemper page 212; sectionn 14.3

I've got a comment on your dimensionof() macro (14.3). I liked it a lot and reimplemented our version of dimensionof() for all compilers that supported the syntax. Unfortunately it bombed in the wrong place. The situation boils down to:

  void f()
  {
    static const struct { int n; int m; } a[] = {{1,2},{3,4}};
    const int size = dimensionof(a);
  }

This refuses to compile as template parameters must have external linkage.

I don't see a clean solution except rewriting the code to use a type with external linkage. But as not all of our compilers support namespaces, it would mean inventing a suitably ugly typename to prevent nameclashes. (So, for now, I commented out the new version.)

I guess this caveat should be mentioned in the errata.

Erratum
29th August 2005 Markus Elfring page 215; listing 14.3

Q: The purpose of the parameter size is unclear for me. It seems that it is not used in the body of the first function make_array_proxy().

A: The first make_array_proxy() invokes the first array_proxy constructor, so there's no need to explicitly specify the size. The compiler "sees" an array (rather than a pointer) inside this function as well as outside.

Question
28th February 2005 Markus Elfring page 241; listing 15.4

The interpret() function return type is Type, and not void.

Typo
29th August 2005 Markus Elfring page 243

Q: Did you consider an alternate code structure, such as the following?

...
}
else
{
  return unknown;
}
...

A: I think the reason I did it as shown was that the strcmp() tests were all in a clearly separate section, denoted by the extra indentation.

It could just as easily be as you say, but that's just not my style.

Question
29th August 2005 Markus Elfring page 251

Q: Which wording do you prefer: "multi threaded" or "multi-threaded"?

A: I think I prefer the latter, but what I prefer most of all is to be consistent. ;)

Question / Typo
15th March 2006 Jonny Rodin page 268; section 16.7.1

The comments for contexts 2 and 3 in the code should be the opposite way round.

Erratum
22nd March 2005 Will Trobaugh page 289; section 18.2.2; listing 18.4

Would you show me a small example of how the returning of the parameter f, where f is a caller-supplied function that is applied to elements of parameter c, would be used?

Thanks for taking the trouble to write to me.

The practice of returning a function object, by value, from an algorithm to which its been passed is widely followed in STL. One important reason is so that one can chain operations succinctly. Passing, and returning, by value is well founded in order to equally support passing function pointers and function object instances.

So, I wrote the for_all_postinc() to return f to follow this convention.

As for an example, I guess one could use it as follows:

  std::vector<int>  vi = ...;
  std::list<int>    li = ...;

  for_all_postinc(vi, for_all_postinc(li, some_function));

The advantage would be where the function object has a non-default constructor, so it saves the coder from having the potentially maintenance-fragile situation of specifying the same thing twice. It also, perhaps, affords the compiler better optimisation opportunity.

Hope that helps.

Question
7th May 2005 Martin Boucher page 338; listing 19.20

In the 3rd ctor of ptr_cast, the member initialisation has a typo.

  ptr_cast(pointer_type pt)
    : m_p(t)

should be

  ptr_cast(pointer_type pt)
    : m_p(pt)

Typo
10th May 2005 Martin Boucher page 344-345; section 20.2,

The declaration
  Resource *m_vs;
Should read:
  VisualSystem *m_vs;

Erratum
28th June 2005 Juan Antonio Zaratiegui Vallecillo page 348; footnote 7

The reference to section 10.11 in fact refers to section 20.11

Typo
12th August 2005 Martin Boucher page 352

There are two scope2 variables. The second one should be scope3

Typo
28th June 2005 Martin Boucher page 380; listing 22.4

class RefCounter also derives publicly from S, as well as from T (as shown in the code snipet from the beginning of section 22.4)

Typo
28th June 2005 Martin Boucher page 380; listing 22.4

The ParentClass token in the member initialiser list for the second constructor should be T.

Typo
17th September 2004 Matthew Wilson page 411; section 25.1.3

This technique, from Chapter 25, was presented to the world in the "Fast, Non-intrusive String Concatenation" article in the June 2004 issue of C/C++ Users Journal. Thanks to a reader - Sean Kelly - for pointing out that the technique assumes that the parameterising string class stores its character data contiguously. That should be ok in practice, since we know of no string class - std or otherwise - that does not do so. Nonetheless, it's a bug, and has been addressed in version 1.8.1 release of the STLSoft libraries.

Erratum
27th May 2005 James Mansion page 422; chapter 26

"Anytime in this chapter that I refer to operator &() it will be the unary form, which is the address of operator. The binary form, which is the bitwise OR operator, is an entirely different beast."

Should read:

"Anytime in this chapter that I refer to operator &() it will be the unary form, which is the address of operator. The binary form, which is the bitwise AND operator, is an entirely different beast."

Typo
12th April 2005 Michael Toksvig page 422; chapter 26

"Anytime in this chapter that I refer to operator &() it will be the unary form, which is the address of operator. The binary form, which is the bitwise OR operator, is an entirely different beast."

Should read:

"Anytime in this chapter that I refer to operator &() it will be the unary form, which is the address of operator. The binary form, which is the bitwise AND operator, is an entirely different beast."

Typo
28th February 2005 Markus Elfring page 438; 17.2.1 (page 273),

The decrement operator "--" has not been printed correctly, instead looking like the "—" character.

Typo
29th June 2005 Martin Boucher page 441; listing 28.1

unused_return_value_monitor constructor should not be explicit, otherwise the code in listing 28.2 (page 442) will not compile. (The reason this crept in is that I condensed the actual separate one parameter and two parameter constructors in the STLSoft class into two for the book listing, and instinctively added the explicit. There's something to be said from compiling one's writing ...

Typo
1st October 2004 Sam Saariste page 510; section 34.2.1

Sam makes the following important point:

"Use of

  std::for_each(&ari[0], &ari[10], print_int);

is incorrect. Even thought it is likely to work for any compiler you will ever use, it is still ill-formed. It should be

  std::for_each(&ari[0], &ari[0] + 10, print_int);

The same applies for

  std::for_each(&ari[0], &ari[dimensionof(ari)], print_int);

which should be

  std::for_each(&ari[0], &ari[0] + dimensionof(ari), print_int);

and for

  std::for_each(&ar[0], &ar[N], f);

which should be

  std::for_each(&ar[0], &ar[0] + N, f);.

Erratum
23rd March 2005 Rajanikanth Jammalamadaka page 514; section 34.3.3

Instead of:
  "Comeau, GCC, and Intel do not supported nested functions in either guise."
it should read:
  "Comeau, GCC, and Intel do not support nested functions in either guise."

Typo
17th September 2004 Matthew Wilson page 521; section 34.4

Since the writing of the book, the refinement of the Range concept has continued, and a new category - the Indirect Range - has been introduced which abstracts callback enumeration APIs. See www.rangelib.org for details. The new category is also discussed in the article "Ranges, part 1: Concepts and Implementation" in the October 2004 issue of C/C++ User's Journal.

Enhancement
23rd March 2005 Rajanikanth Jammalamadaka page 521; footnote 7

Instead of:
  "John was also a one of the reviewers for this book"
it should read:
  "John was also one of the reviewers for this book"

Typo
15th August 2005 Martin Moene page 579

The Vandevoorde and Josuttis book is "C++ Templates - The Complete Guide", rather than "C++ Templates - The Comprehensive Guide".

Typo
 

Click through to Amazon.com
Valid XHTML 1.0! Imperfect C++ content copyright Addison-Wesley | Additional content copyright Synesis Software Pty Ltd and Greg Peet
Website designed by Greg Peet. Thanks Greg!