Scott Meyers
Modification History and Errata List for Effective C++, Third Edition

Last Updated March 17, 2008
by Scott Meyers

Note: This document applies to only the third edition of Effective C++. Errata for earlier editions of the book are available as follows:

What follows are my notes on what I've changed in the third edition of Effective C++ since its original publication (i.e., since its first printing) and what I believe may need to be changed in future printings. Most of the changes (or prospective changes) are cosmetic and don't affect the technical content of the book. To distinguish those modifications that do affect technical material, I precede those entries with an exclamation mark ("!") and display them in red.

Each entry includes the following information:
  • Date Reported: The date the problem was brought to my attention.
  • Who: The initials of the person reporting the problem. The initials "sdm" refer to me. The mapping from other initials to full names is at the bottom of this document.
  • Pages: The pages of the book (or the Item number) affected.
  • What: A description of the problem and the solution.
  • Date Fixed: The date on which I fixed the problem. If no date is shown, it means I haven't gotten around to fixing the bug or I'm still mulling over whether I want to fix it. Sometimes I change my mind on bug reports, so prospective bugs often spend quite a while in the "not yet fixed" state. When Addison-Wesley notifies me that a new printing is about to take place, I go through the bugs and fix all those I've decided must be fixed. It's thus not uncommon for all the bugs fixed for a particular printing to have the same fix date.
The easiest way to use this list is to find out which of the book's printings you have (it's listed on the copyright page near the bottom), then go to the appropriate section of the list and read from that point forward. For example, if you have a copy of the third printing, the changes made to the first and second printings won't apply to you, because the changes will already be in place in your copy of the book.

I am always interested in bug reports and suggestions for improvements to Effective C++. To submit comments, send email to ec++@aristeia.com .

To be assured of always having the most accurate version of Effective C++ at your fingertips, I encourage you to buy a copy of each printing :-).


The following changes were made for the second printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's the first printing.
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  ------------------------------------------------  --------
   6/ 1/05 rxy    30  References to the variable "theFileSystem" should  7/ 4/05
                      be replaced with the variable "tfs" in the last 
                      two sentences.

   6/ 2/05 rxy    52  In 4th line of 2nd para, "that going" ==> "than    7/ 4/05
                      going". 

   6/ 2/05 rxy    79  In the third code example, "Date d(2, 20, 1995)"   7/ 4/05
                      is incorrect, because that's a valid date.  
                      I changed the example to "3, 40".

   6/ 2/05 rxy    83  2nd line of 1st bullet.  "Your should" ==> "you    7/ 4/05
                      should". 

   5/ 4/05 jxr   122  In code at top of page, SpecialWindow::blink       7/ 4/05
                      has an unnecessary semicolon at the end of its
                      definition.

   6/ 6/05 sdm   231  There's unnecessary extra vertical space after     7/ 4/05
                      the last statement in the 2nd impl of doAdvance.

The following changes were made for the third printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first two printings.
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  ------------------------------------------------  --------
   8/19/05 axf     4  In last para, "objects of user-defined types"     10/10/05
                      ==> "objects generated from structs and classes". 

   7/ 5/05 bxm    20  In several code examples, the quote character is  10/10/05
                  21  "`" instead of "'".  

   7/ 5/05 bxm    31  I added a comment at the end of the next-to-last  10/01/05
                  32  para on pg. 31:  "Actually, it's only part of
                      a Singleton implementation.  An essential part of
                      Singleton I ignore in this Item is preventing the
                      creation of multiple objects of a particular type."

   7/ 5/05 bxm    81  In 2nd-to-last sentence, "delete" should be in    10/10/05
                      code font.

   7/11/05 gxk    82  In 2nd-to-last para, "pInv" ==> "retVal."         10/10/05

   7/26/05 bxm    86  Explicitly declare Student destructor virtual.    10/10/05
                      (It's already implicitly virtual.)

   9/26/05 mxs    93  In last para, I added this footnote:  "The        10/10/05
                      destructors will be called once at program
                      shutdown."

   8/24/05 jds   105  Extra space before the period in the last line    10/10/05
                      before the "Things to Remember" heading.

   7/26/05 bxm   115  Remove "std::" qualification in definition of     10/10/05
                      the variable encrypted for consistency with 
                      page 114.

   7/26/05 bxm   124  In 2nd-to-last line, "ulhc and lrhc are declared  10/10/05
                 125  private" ==> "ulhc and lrhc are supposed to
                      be private to their Rectangle".
 
   7/ 8/05 ixl   125  In 2nd-to-last para, "upperRight" ==>             10/10/05
                      "lowerRight".

   7/11/05 gwj   126  "It" at beginning of 2nd sentence of "Things to   10/10/05
                      Remember" bullet is ambiguous.  Reword.

   8/18/05 clt   160  The example at the bottom of the page is odd,     10/10/05
                      because Derived::mf1 calls Base::mf1, which is
                      pure virtual.  I added an xref to Item 34, which
                      explains that pure virtuals may be defined.

   7/26/05 bxm   162  In 3rd para, error should be private it if it's   10/10/05
                      only called by member functions.  Hence "is
                      called by member functions if they need to report
                      an error" ==> "is called when an error needs
                      to be reported". 

! 10/ 5/05 jsl   174  In 2nd prose paragraph, the definition of         10/10/05
                      compatibility is incorrect.  A callable entity
                      is compatible if a const GameCharacter& can be
                      passed to it, i.e., if its parameter type is 
                      either const GameCharacter& or something that 
                      a const GameCharacter& can be implicitly 
                      converted into.

! 10/ 5/05 jsl   175  The first sentence of the last paragraph is       10/10/05
                      inaccurate. It's not the "_1" that specifies
                      that currentLevel is to be used as the GameLevel
                      object when calling GameLevel::health, it's the
                      location of currentLevel in the parameter list
                      to tr1::bind.  The "_1" itself, in conjunction
                      with its position in tr1::bind's parameter list,
                      specifies that the argument passed to the
                      function object generated by tr1::bind should
                      then be passed as the parameter to
                      GameLevel::health.  I reworded to avoid
                      mentioning _1 at all.

   7/25/05 tdh   207  In 3rd para, "vary" ==> "varies".                 10/10/05

  10/12/05 jsl   231  In first para, "create two versions" ==>          10/10/05
                      "create multiple versions". 

   8/ 1/05 bxm   242  As return type of operator new or as an unnamed   10/10/05
                 244  parameter, "void *" ==> "void*".  This it to
                 245  follow consistent conventions in the book.
                 252
                 254
                 255
                 258

  10/ 5/05 sdm   263  The target year for C++0x has been set at 2009,   10/10/05
                 264  with all substantive work finished by the end
                      of 2007.  (It takes a year or so after all work
                      is done to make the new standard official.)

! 10/ 5/05 sdm   266  In 1st para, "anything convertible to an int" ==> 10/10/05
                      "anything an int can be converted into".

   9/11/05 pxh   269  In 1st bullet at top of page, "C99"==> "C89".     10/10/05

The following changes were made for the fourth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first three printings.
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  ------------------------------------------------  --------
   1/26/06 ser    32  In tempDir, initialization of td is missing          6/17/06
                      "( params )".

   1/25/06 bxm    47  Code for ~DBConn is missing a close } for the      6/17/06
                      opening if statement, and the block controlled
                      by the if needs to be indented.

   2/17/06 clm    62  In para after 2nd code fragment, "continue or      6/17/06
                      goto statement" ==> "break or goto statement". 

   3/16/06 jeh    62  "Regardless of how the delete were skipped," ==>   6/17/06
                      "...were to be skipped,"

   3/27/06 axd   105  Reword bullet at bottom of page, because non-      6/17/06
                      member functions don't have a this pointer.

  12/23/05 vxs   158  In 3rd para, "Derived's overloading of mf3" ==>    6/17/06
                      "Derived's declaration of mf3". 

   1/ 4/06 vxs   183  In last two paras, "overridden/overriding" ==>     6/17/06
                      "redefined/redefining".

   3/16/06 jeh   201  "con-stnesses" ==> "const-nesses".                 6/17/06

  12/29/05 sdm   210  In 3rd para, "Object-oriented" ==>                 6/17/06
                      "Object-Oriented".

  11/17/05 axh   229  Both nested iterator classes should end with a     6/17/06
                      semicolon instead of a colon.

   3/27/06 axd   230  The 3rd-to-last para says that the typeid          6/17/06
                      test will cost us at runtime, but a good
                      optimizer might eliminate the test.  Reword.

   3/12/06 txs   234  In comment in last code fragement, "error!" ==>    6/17/06
                      "error!  won't compile".

   4/28/06 sdm   247  In last bullet of Item 49, "subsequent" ==>        6/17/06
                      "associated".

   1/ 1/06 kxk   257  Missing comma after declaration of parameter       6/17/06
                      pMemory in operator delete near middle of page.

  11/13/05 jxc   293  Index entry for RAII should refer to page 63       6/17/06
                      instead of page 66.

The following changes were made for the fifth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first four printings.
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  ------------------------------------------------  --------
   8/2/06 bxs     18  One way to remember what const refers to when     11/21/06
                      pointers are involved is to read the declarations
                      right to left:  
                        char *p              // ptr to char
                        const char *p        // ptr to char that is 
                                             //   const
                        char const *p        // ptr to constant char
                        char *const p        // constant ptr to char
                        const char * const p // constant ptr to char 
                                             //   that is const
                        char const * const p // constant ptr to 
                                             //   constant char
                      I added a footnote mentioning this idea.

   7/28/06 lfr    46  In middle code example, red block is terminated   11/21/06
                      with a black brace.  The brace should be red.

!  7/17/06 nxd   108  Text after top code example says that STL         11/21/06
                      containers specialize std::swap.  This is 
                      incorrect; they overload std::swap as 
                      described on page 109. I changed 
                      "specializations" to "versions" to dance around
                      this issue until it's discussed on the next
                      page.

   8/26/06 lfr   177  Missing "of" in last sentence of 2nd para.        11/21/06

! 10/31/05 clt   214  The "this->" in SquareMatrix::invert is           11/21/06
  10/ 4/06 hgv   215  unnecessary, because the using declaration for
                 281  SquareMatrixBase::invert allows the name "invert"
                 291  to be looked up in the base class (as noted on
                 295  page 211).  I updated the comment for the 
                      using declaration to indicate that both Items 33
                      and 43 are being addressed, and I modified the
                      text of the following paragraph.  These changes
                      modified the page break with page 215 and also
                      eliminated some index entries.

   1/18/06 vxp   214  To prevent the code bloat discussed in this       11/21/06
                      Item, it's important that 
                      SquareMatrixBase::invert not be declared inline.

   7/ 7/06 yxf   286  The entries
                        LoggingMsgSender::sendClear 208, 210
                        LogginMsgSender::sendClear 210, 211
                      should be merged as
                        LoggingMsgSender::sendClear 208, 210, 211

The following changes were made for the sixth printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first five printings.
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  ------------------------------------------------  --------
   5/08/07 sdm  xvii  In first para, "about five years" ==> "about       5/08/07
                      three years" and "two decades" ==> "nearly two
                      decades".

   6/29/06 axd    22  Add a remark that the definition of "const" that   5/08/07
                      programmers should follow for const member 
                      functions is logical constness, not bitwise
                      constness.  (The information is already bullet 2 
                      on page 26, but putting it here makes the
                      point sooner.)

  12/31/06 ahh    26  In 2nd summary bullet, "conceptual constness"      5/08/07
                      ==> "logical constness".

  10/14/05 ejx    30  Reworded code comments to make clearer that the    5/08/07
                      code on this page would be in a header file and
                      that tfs' definition would be in a separate .cpp
                      file somewhere.

   2/25/07 mxr    36  In first code example, "<class T>" ==>             5/08/07
                      "<typename T>" (for consistency with pg. 35).

  12/31/06 ahh    37  In second para, "If you want to support            5/08/07
                      assignment" ==> "If you want to support copy 
                      assignment".

   6/27/06 bp     71  To Font class at top of page, add a "..." to the   5/08/07
                      code and a comment that, per Item 14, the class
                      must handle copying somehow.

   3/27/07 dxs   209  Last line of last code comment should read         5/08/07
                      "// sendClear is omitted".

  12/31/06 ahh   216  In 2nd prose para, "simple inline calls to base    5/08/07
                      class versions" ==> "simple inline calls to
                      (non-inline) base class versions."

   2/ 8/06 awo   230  In first code example, "IterT" ==> "T" (because    5/08/07
                      the pointer itself is the iterator, T is just
                      what it points to).

The following changes were made for the seventh printing of the book. These changes apply to your copy of Effective C++, Third Edition only if it's one of the first six printings.
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  ------------------------------------------------  --------
   9/15/07 dmr     7  Wrong type of quotes in "Darla".                   1/28/08

   3/18/07 mxr    55  Final sentence of top para is not technically      1/28/08
                      correct, because C++ implementations are allowed
                      to change the value of a deleted pointer,
                      although I don't know any that do.  

   5/10/07 sdm   107  In second code fragment, move "this won't compile" 1/28/08
                      comment to the line trying to access the
                      pImpl pointers.

   9/15/07 dmr   118  Should mention that the two cast forms shown at    1/28/08
                      the top of the page yield identical behavior,
                      e.g., both create temporary Widget objects.

   9/15/07 dmr   125  In 1st para, comma preceding the parenthetical     1/28/08
                      comment should be a period.

   9/15/07 dmr   145  In comment at top of page, "exactly the same       1/28/08
                      member functions" ==> "exactly the same public
                      member functions".

!  7/28/07 mxh   158  In first line on page, "containing Base" ==>       1/28/08
                      "containing Derived".

! 12/22/07 lfr   193  In 1st para, "checkOut" is ambiguous during name   1/28/08
                      lookup, not overload resolution; and the two 
                      "checkOut" functions are not equally good
                      matches, because one is const and one is not.
   
   7/17/07 mxr   197  Class definition of PersonInfo should match that   1/28/08
                      shown on page 195.
 
  10/ 3/07 bxj   239  3rd para should make clear that the new-handler    1/28/08
                      is a global resource and thus subject to the
                      thread-safety issues that apply to all such
                      resources.

The following changes have been proposed but have not yet been published:
    DATE                                                                  DATE
  REPORTED WHO PAGES  WHAT                                                FIXED
  -------- --- -----  --------------------------------------------------  -----
  11/ 4/07 nxd 18-19  The text implies that all by-value returns should 
                      be const, but cases where non-const by-value
                      returns are good design are not difficult to find,
                      e.g., return types of std::vector<T> where callers
                      will use swap with an empty vector to "grab" the
                      return value contents without copying them.
                      Reword. 

What follows are interesting comments about the material in Effective C++, Third Edition, but I don't expect to be able to modify the book to take these comments into account until (if ever) I write a fourth edition.
  DATE
REPORTED WHO  PAGES  WHAT
-------- --- ------- ----------------------------------------------------------
 9/26/06 jxm       2 The book says it limits itself to standard C++, but the
                     book also shows use of non-standard libraries such as TR1
                     and Boost.  (This is true, but the book uses no
                     non-standard language features, only portable libraries 
                     presenting standard-conforming interfaces.)

 5/ 6/05 exa  Item 2 "In one of my recent projects, I have to use 2 third party
                     libraries and both of them had a symbol define with the 
                     same name, like in one library
                       #define SOMETHING 1
                     and in another
                       #define SOMETHING 2
                     now, while compiling, the second one overrights the first
                     one. I tried with the namespace, but still no luck, later
                     on, I've to do the manual stuff. At that time, I really
                     appreciated your Item about avoiding #define.
                        I didn't find this specific issue in your item (and not
                     anywhere else also), so I'm just forwarding it to you."

11/ 2/07 nxd  18-19  Declaring by-value function return values const will
                     prevent their being bound to rvalue references in C++0x.
                     Because rvalue references are designed to help improve
                     the efficiency of C++ code, it's important to take
                     into account the interaction of const return values
                     and the initialization of rvalue references when
                     specifying function signatures.

 9/12/05 pxh      24 Unfortunately, even const_cast can't be used to cast a
                     const_iterator to an iterator.  For details, consult Item
                     27 of Effective STL (available online as part of 
                     my June 2001 CUJ article, where it's known as Guideline 2)
                     as well as the newsgroup discussion of the matter.

11/21/06 pxw      32 pxw reports that some compilers (notably Sun's) won't
                     inline functions containing static data.  Compilers
                     don't have to inline anything, but if inlining is
                     important to you, be on the lookout for this issue.

 7/25/05 tdh   33-34 Using functions to return references to local static
                     objects is a good way to avoid referring to uninitialized
                     objects, but local static objects are automatically
                     destroyed (in the reverse order in which they were
                     constructed) at program shutdown, and this means that it
                     is possible for the destructor of one local static object
                     to refer to another local static object that has already
                     been destroyed.  [For a good discussion of this problem
                     and two possible ways to deal with it, consult sections
                     6.5-6.8 of Andrei Alexandrescu's Modern C++ Design.
                     --Scott]

 7/28/06 lfr  Item 6 Inheriting from a base class like Uncopyable or
                     boost::noncopyable can be more convenient than manually
                     declaring the copying functions private, because the base
                     class does not disable the automatic generation of a
                     default constructor, but manually declaring a copy
                     constructor does (per Item 5).  

11/26/06 nxd  Item 6 If a class C declares the copying functions private and
                     defines a function f that performs copying, but f is never
                     called, the code will compile and link.  (If f is called,
                     the code will not compile.) To prevent this (unlikely)
                     problem, nxd suggests: 
                     - Have C's operator= return an incomplete type.
                     - Declare C's copy constructor explicit (i.e., prefix it
                       with the "explicit" keyword).

 9/ 8/05 wxv      47 wxv notes that if a client calls DBConn::close, and that
 2/ 3/07 sxf         call throws an exception, the database did not close
                     successfully, but in some libraries, calling close on it
                     again (in the DBConn destructor) would be harmful.  It
                     might thus be better to use an enum instead of a bool to
                     keep track of the state of the database, e.g.,
                       enum DBStatus { Open, Closed, AttemptToCloseThrew };
                     sxf argues that this approach leads to the destructor
                     trying to close the connection again if the call to close
                     throws, and that puts us back in our original position.
                     A better design might be to change the enum to
                       enum DBStatus { Open, CloseAttempted };
                     and not try to invoke close if it's already been called.

 6/27/06 pxg Item 15 A way to minimize the need to access raw resources is
                     to wrap legacy APIs with ones that know about resource
                     managers.  For example, daysHeld (at the bottom of 
                     page 69) and releasefont (at the bottom of page 70) could
                     be augmented with these functions, which clients could
                     then call with resource-managing objects: 

                       int daysHeld(const std::auto_ptr<Investment> p)
                       { return daysHeld(p.get()); }

                       void releaseFont(Font f) { f.get(); }

 6/12/05 sdm Item 17 The reasoning in this Item applies to more than just
                     dynamically allocated memory.  It should be revised to
                     apply to resource acquisition in general. 

 6/19/05 mxm Item 23 mxm notes that this Item doesn't discuss the ramifications
                     of the different calling syntaxes for member and non-member 
                     functions.  However, I do discuss this issue in the article-
                     length treatment of this topic.  (Scan for "Syntax Issues.")

 8/26/07 mxd Item 23 "A C++ pattern that I have often seen is that there'd be a
                     big hairy class with a ton of methods that all work
                     together to get some giant job done.  If a certain style
                     is followed, the logic of that job can be very hard to
                     follow.  That style is having MethodA do a ton of work and
                     then call MethodB (and possibly MethodC, MethodD, ...,
                     MethodZ) with few if any arguments to the call.  The
                     methods are all of the same class, so basically they are
                     handing off "arguments" to one another by what amounts to
                     file-global variables: the member variables of the class.
                     In my mind the self-documenting quality of a piece of code
                     is carried almost entirely on the shoulders of the names
                     of functions and arguments passed to them.  If you throw
                     away the arguments you lose half the visual meaning behind
                     every method call, and it makes the code terribly hard to
                     read.  In other words, whenever you see MethodA call
                     MethodB in the same class, all you know vis-à-vis the
                     data flow is that it involves (a) the arguments passed
                     (if any) and (b) a potentially arbitrary subset of the
                     member variables.  It’s just plain global-variables
                     lite. And it is avoided completely if you stick to
                     non-member, non-friend functions as much as possible."
 
 7/19/06 nxd 110-111 Putting "using std::swap;" in a function calling swap is
                     not sufficient to ensure that the proper swap will always be
                     called.  For details, consult this Usenet thread
                     devoted to this topic.  The C++ Standardization
                     committee has addressed the broader issue present here via 
                     a defect report on the matter. 

 6/ 7/07 clt 115-116 If the operand to the assignment in loop Approach A is
                     not of a type taken by a Widget assignment operator, a
                     temporary may be introduced.  If this happens, each
                     call to Widget's operator= will incur the cost of a
                     temporary construction and destruction.

 6/29/05 dxe Item 27 One way to reduce the need for downcasts is to take
                     advantage of C++'s support for covariant return types in
                     member functions like clone and in factory methods.

 8/23/05 bgn    126  The example does not make the case very well, because even
                     if upperLeft and lowerRight returned Point objects by
                     value, pUpperLeft would still dangle at the end of the
                     statement.

 8/24/05 bgn Item 31 "We work on embedded systems, but often we want to run our
                     code on PC's in a simulation environment, or perhaps
                     perform testing before our custom hardware has been built.
                     So for those hardware dependent classes (such as modems,
                     serial ports, etc) we sometimes use the pimpl idiom and
                     pick a different implementation file (.cpp file) in our
                     makefiles at build time. This let's us seamlessly run our
                     code in multiple environments w/o resorting to making base
                     classes, using inheritance, and making factory
                     functions. We've gotten a lot of mileage out of that."

 9/ 2/05 bxm Item 31 "All our Interfaces have a unique Prefix,.e.g class
                     IPerson, class IShape, etc, so we prefix all Interfaces
                     with I.  This is simple but very effective. A programmer
                     does NOT have to look into the class and see if there is
                     a pure virtual function. The name says all ;-)
                       We have created a new keyword IMPLEMENTS for class
                     implementers so it looks very like java:
                        #define IMPLEMENTS public /* or virtual public */
                     E.g. in c++ we write: class PersonImpl : IMPLEMENTS
                     IPerson.  So the programmer can distinguish between
                     public inheritance and interface inheritance. You can do
                     the same with EXTENDS when interfaces inherit from
                     interfaces (in C++)..."

10/ 5/05 jsl    175  In the call to tr1::bind, currentLevel is passed by
                     value.  A (typically preferable) alternative is to pass a
                     pointer to currentLevel.  
                       I (Scott) also note that another alternative -- one in
                     accord with Item 20 -- would be to pass currentLevel by
                     reference-to-const.  This can be done using tr1::cref,
                     which is not discussed in the book.  The call would look
                     like this:
                       std::tr1::bind(&GameLevel::health,
                                      std::tr1::cref(currentLevel), _1);

 8/31/06 bxm Item 41 In C++0x, it is highly likely that a new language feature
                     known as "concepts" will make it possible to make implicit
                     interfaces explicit.  Until such a feature exists, it is
                     possible to use the Boost Concept Check Library for this 
                     purpose.

12/10/07 sxo    226  The doMultiply template can be eliminated by structuring
                     the code as follows: 

                       template<typename T> class Rational;

                       template<typename T> 
                       const Rational<T> operator*(const Rational<T> &lhs, 
                                                   const Rational<T> &rhs);

                       template<typename T> 
                       class Rational {
                         // declaration/definition of non-templated operator
                         friend const Rational<T> operator*(const Rational<T> &lhs, 
                                                            const Rational<T> &rhs) 
                         {
                           return operator*<T>(lhs, rhs);
                         }

                         ...

                       };

                       // definition of templated operator
                       template<typename T> 
                       const Rational<T> operator*(const Rational<T> &lhs,
                                                   const Rational<T> &rhs)
                       {
                           return Rational<T>(lhs.numerator() * rhs.numerator(),
                                              lhs.denominator() * rhs.denominator());
                       }

12/10/07 sxo 231-232 The tag arguments passed to the doAdvance functions may,
                     depending on compiler/linker optimizations, incur a
                     runtime cost.  Such cost can be eliminated by writing the
                     code this way:

                       // declaration for helper class
                       template<typename IterT, typename DistT, 
                                typename TagT = typename std::iterator_traits<IterT>::iterator_category>
                       class Advance;

                       // specialization of above for random access iterators
                       template<typename IterT, typename DistT>
                       class Advance<IterT, DistT, std::random_access_iterator_tag> {
                       public:
                         static void DoAdvance(IterT &iter, DistT d) 
                         { iter += d; }
                       };

                       ...                   // other specializations go here

                       template<typename IterT, typename DistT>
                       void advance(IterT &iter, DistT d)
                       {
                         Advance<IterT, DistT>::DoAdvance(iter, d);
                       }

 3/24/07 hxs    235  In 2nd para, the comment that TMP allows for the declaration
                     of variables is potentially misleading, because such "variables"
                     can't vary:  once they are initialized to a value, that value can
                     never change.  TMP is a functional language, hence offers no 
                     support for assignment.  TMP variables are akin to const
                     "variables" in C++.

 4/20/06 jeh    243  NewHandlerHolder would be easier for clients to use if
                     they passed the new new_handler instead of the old one,
                     i.e., if the NewHandlerHolder constructor called
                     set_new_handler itself.  (In this case, the class might be
                     better named something like NewHandlerInstaller, instead.)

10/22/05 sdm    265  Technically, tr1::weak_ptr isn't a smart pointer,
                     because it doesn't overload operator->.

11/13/05 mxd    NA   It would be nice to have an Item exhorting readers to
                     use a lint-like tool as part of their development process.

Who's who:
  jxr = Jason Ross          
  rxy = Robert Yokota       
  exa = Ejaz Anwer          
  mxm = Marc Mutz           
  dxe = Dick Eimers         
  ixl = Idan Lupinsky       
  bxm = Bernhard Merkle     
  gwj = G. Wade Johnson     
  gxk = Gerhard Kreuzer     
  tdh = T. David Hudson     
  clt = Clovis Tondo 
  axf = Attila Feher 
  bgn = Brian Neal   
  jds = J. Daniel Smith
  pxh = Phillip Hellewell
  wxv = Walter Vannini
  mxs = Marcin Sochacki
  jsl = Joshua Lehrer
  ejx = Ed Ji Xihuang
  jxc = Jiongxiong Chen
  mxd = Michael Drumheller
  axh = Andrew Henrick
  vxs = Vincent Stojanov
  kxk = Ken Kobayashi
  ser = Eldar Ronen
  vxp = Vasily Poshehonov
  awo = Tony Oliver
  clm = Cameron Mac Minn
  jeh = John Hershberger
  txs = Thomas Schell
  axd = Alex Dumov
  bp  = Balog Pal               
  pxg = Paul Grenyer
  yxf = Yukitoshi Fujimura
  nxd = Niels Dekker
  lfr = Fraser Ross
  bxs = Balbir Singh
  hgv = Harsh Gaurav Vangani 
  jxm = Jürgen Messerer
  mxr = Mike Rizzi
  ahh = Alex Howlett
  sxf = Solomon Foster
  dxs = David Solomon
  hxs = Hendrik Schober
  pxw = Peter Weinert
  mxh = Miaohua
  bxj = Brian Johnson
  dmr = Martin Rottinger
  sxo = Sergei Otarov 

From here you may wish to visit the Amazon Page for Effective C++, Third Edition.

Scott Meyers
Software Development Consultant
3051 SW Turner Road
West Linn, OR 97068

Voice: 503-638-6028
Fax: 503-638-6614
Email: smeyers@aristeia.com