Sunday, June 30, 2002

July Seminar Updates

Two quick notes about upcoming seminars with or by me:
- My workshop with Bruce Eckel has been cancelled.
- An excellent opportunity to take my Intro. STL course.


Workshops on Policy-Based Design
--------------------------------
The workshop on Policy-Based Design (PBD) and Patterns that Bruce Eckel and
I had planned to lead on July 18-19 in Crested Butte, Colorado, has been
cancelled. The people who signed up for it were as excited about it as we
were, but we ultimately decided that there just weren't enough of them to
make the event viable. That's too bad, because I think it would have been
both useful and fun. However, if you're a C++ Head (highly likely, if
you're on this list), there's still the one-day workshop on PBD that Andrei
Alexandrescu and I will be leading on October 31. Registration for that
should open around the middle of July. When it does, I'll let you know via
this mailing list.

An Effective Introduction to the STL
------------------------------------
July 22-25, Leor Zolman will be teaching my introductory hands-on STL
seminar at the SPC in Vancouver, CA. You can read about the seminar and
how I hand-chose Leor to teach it at
http://www.spc.ca/training/public/stlintro.htm, but here I want to focus on
two other things. The first is the cost. Assuming you are paying in
American dollars, the full four-day seminar costs only about $1300. This
is a great deal. The second is the need to register as soon as possible,
ideally this week, because enrollment is limited. (That's to make sure
that Leor has enough time to give everybody who attends the personalized
attention they deserve.) Regardless of the OS or C++ compiler you use, if
you've been thinking you'd like to learn about or better understand the
STL, this seminar is the way to go.

Scott

Thursday, May 2, 2002

Interactive Design Workshops in July and October

I have two unique workshops to announce:
- "Policy-Based Design and Patterns" with Bruce Eckel, July 18-19.
- "Policy-Based Design" with Andrei Alexandrescu, October 31.
Both are immersive, hands-on, and of limited enrollment. Details follow.

"Policy-based design" (PBD) is the term Andrei Alexandrescu uses to
describe the approach to systems building he describes in his book, "Modern
C++ Design." I've been intrigued by Andrei's ideas since before he
published them, as I was lucky enough to read several pre-pub drafts of his
manuscript.


JULY 18-19 WORKSHOP WITH BRUCE ECKEL

Within the C++ community, most attention has focused on Andrei's unique
implementation techniques (e.g., template templates) and their remarkable
ability to reduce compilers to rubble. I believe that Andrei's approach is
more general than the language in which it is implemented, however. I
believe it is a general approach to OOA and OOD, and that it can be
profitably applied to any OO language.

With that in mind, I approached my colleage and friend, Bruce Eckel (see
below for information on Bruce, if you are not already familiar with him),
and proposed that we jointly host a workshop on language-agnostic PBD. The
general idea is to get a bunch of software developers in a room, describe
PBD, then work through a series of real problems in small groups, applying
PBD to each of them, ultimately having participants develop an
implementation in whatever OO language they like. Unlike lectures and
seminars where the speakers speak and the attendees listen, this will be a
highly interactive event. This is not about listening to a description of
PBD and seeing how it is done, this is about doing PBD yourself, about
experiencing its strengths and weaknesses firsthand, about learning how to
map it to the implementation language of your choice.

It's also about discussing the relationship between PBD and patterns. One
of Andrei's original goals in developing PBD was to make it possible to use
C++ templates to generate implementations of GOF patterns, and his book
shows how to do that. But is it possible that PBD is itself a pattern?
Bruce leans towards the idea that it is. I'm a bit more conservative, but
there are clear relationships between PBD and the GOF's Strategy, Template
Method, and Abstract Factory patterns. One of the goals of the workshop
will be to ferret out how PBD and patterns relate, possibly concluding with
a PBD-as-pattern write-up. Who knows, participating in the workshop may
put you in on the ground floor of the identification of an important new
pattern.

Bruce and I are still working out the details of this workshop, but we know
this much: it'll be July 18-19 in Crested Butte, Colorado, and enrollment
will be limited to 30 people. For more information, take a gander at
http://www.mindview.net/Seminars/PolicyPattern/.

Here's some brief background on Bruce: Author of Thinking in C++, author of
Thinking in Java, author of Thinking in Python (available, but under
development), author of Thinking in Patterns (also under development). All
his books are freely downloadable; he has been a pioneer in electronic
publishing, too. For more on Bruce, visit his web site:
http://www.mindview.net/.


OCTOBER 31 WORKSHOP WITH ANDREI ALEXANDRESCU

But as a reader of this newsletter, there's a decent chance your primary
interest in Andrei's work is in applying it in all its templatized glory in
C++. Sure, reading Andrei's book and articles in CUJ is interesting, but
how do you go about taking the ideas behind PBD and actually putting them
into practice on real projects? I suggest you ask Andrei. Better yet,
watch Andrei. Better still, DO IT WITH ANDREI. Oh, I'll be there, too. I
like to think I know a thing or two about PBD, and by the time I'm done
with the seminar in July with Bruce, I know I will.

The workshop that Andrei and I will be hosting will be similar to the one
I'm doing with Bruce, but with two important differences. First, it's only
one day long. Second, it's for hard-core C++ developers. Namby-pamby
programmers in Java, C#, Python, etc., should attend the July workshop
unless they're prepared to jump feet-first into a thicket of angle
brackets. Like the seminar I'm doing with Bruce, this one will be based on
immersive, interactive problem-solving that results in real code. It's not
about us lecturing and you listening. It's about all of us working
together (sometimes in small groups) to take interesting high-level
problems, break them down via PBD, then implement them using your favorite
C++ compiler.

The workshop will have limited enrollment, probably around 25. (Andrei and
I haven't yet worked out the details.) Furthermore, we'll be running it as
an optional fourth day add-on for attendees of the next "THE C++ Seminar,"
(TCS3) which will be held near Portland, Oregon, on October 28-30. (It
will actually be held in Vancouver, Washington.) If you're interested,
pencil those dates in (October 28-31). Registration for this workshop
won't open until registration for TCS3 does, and that won't happen until
about July 15.

To be the first on your block to know when registration is available,
subscribe to the TCS mailing list
(http://groups.yahoo.com/group/cpp_seminar/). The opening of registration
will be announced there first, always a few days before it's announced to
my mailing list, Herb's mailing list, Steve's mailing list, etc.

I hope to see you in Crested Butte in July, in Vancouver in October, or
both!

Scott

Thursday, March 28, 2002

Possible open-enrollment seminars this summer

I am considering offering some open-enrollment courses near Portland,
Oregon, this summer, and I'd like to get some idea of which courses would
be of the greatest interest. In theory, I could offer any of the courses
listed at my Training Page (http://www.aristeia.com/training_frames.html),
but the following are the ones I'm most actively considering:

High-Performance C++ Programming
1 Day
Description at http://www.aristeia.com/high-performance_frames.html

Effective C++ Programming
5 Days
Description at http://www.aristeia.com/effective-c++_frames.html

Effective STL Programming
2 Days
Description at http://www.aristeia.com/estl/index_frames.html

An Effective Introduction to the STL
4 Days
Description at http://www.aristeia.com/eistl/index_frames.html

Cost would probably be around $500/day and would include continental
breakfast, buffet lunch, afternoon snack, and an unlimited supply of
beverages.

If you think that you or your colleagues would be able to attend a seminar,
please let me know the topics and time frame that would be best for you, as
well as the number of people. If you are interested in a topic not listed
above, please let me know that. If you think that you and your colleagues
would be unlikely to attend a seminar this summer, please do not reply to
this message.

Thanks for your help with this.

Scott

Friday, March 22, 2002

The Effective Software Development Series

For over a decade, I have tried to help bring outstanding books on software
development into existence. I've written my books and CD, I've reviewed
piles of pre-pub manuscripts for Addison Wesley, and I've encouraged
prospective authors who I thought had something important to say (perhaps
most notably Andrei Alexandrescu). Now I'm pleased to report that I'll be
acting as Consulting Editor for a new Addison Wesley book series, the
Effective Software Development Series.

I've put together a preliminary series overview, and you can find it at
http://groups.yahoo.com/group/scott_meyers/files/ESDS%20Overview.pdf
I hope you'll take the time to read it (it's only a page and a half), but
if you're in a hurry, this is the executive summary:

The Effective Software Development Series (ESDS) provides expert advice
on all aspects of modern software development. Books in the series are
well-written, technically sound, of lasting value, and tractable
length. Each describes the critical things the experts almost always do
-- or almost always avoid doing -- to produce outstanding software.

The series has just been started, and though there are things going on
behind the scenes, we're not yet in a position to announce any titles. So
why am I telling you this? Primarily to let you know that if you are
interested in writing a book that you feel would be a good fit for the
series, or if you know anybody who might be interested in writing a book
that you think would mesh well with the series, we'd love to hear about it.
Good books require good manuscripts, and good manuscripts require authors
with development insights and experiences that make them masters in their
fields. I know that many people on this mailing list are such master
developers, and I know that they know other master developers. I want to
help make the expert advice of such developers more widely available, and
I'm hoping you'll help me do that.

For information on submitting a manuscript or a proposal, feel free to
contact me (smeyers@...) or Mike Hendrickson, the AW editor for
this series (mikeh@...).

Thanks,

Scott

Monday, March 11, 2002

Updated Effective C++ CD Errata List

I just updated the Effective C++ CD errata page
(http://www.aristeia.com/BookErrata/cd1e-errata_frames.html) with the
latest batch of bug reports, as well as with a revised version of the bug
report regarding problems using IE6. That, along with the corresponding
bug report for NS6, are the most important new entries. Here's the full
list:

9/18/01 dp Under IE6, image and chunk size choices don't appear in
the navigation area, and lines don't break properly to
fit the browser window. For more information on the CD
and IE6, see href="http://groups.yahoo.com/group/scott_meyers/message/36">the message I
posted to my mailing
list on the subject
. (Despite these problems, many
people seem to feel that the CD works acceptably well
under IE6.)

11/10/01 sdm Change all URLs and email addresses that mention
awl.com to URLs/email addresses at aristeia.com
because, despite over six years of trying, the web
morons at AW are incapable of maintaining valid URLs
and email addresses.

1/19/02 ecm The CD doesn't work properly with Netscape 6.2. In
particular, images are not displayed correctly, and
chunk and image sizes are not indicated in the
navigation area.

1/22/02 ds In the magazine article "Counting Objects in C++,"
the comment in the second class definition after P55 is
incorrect: "rest of Widget" ==> "rest of ABCD"

2/ 1/02 am In the MEC++ appendix, "An auto_ptr Implemention," the
out-of-line implementation of the generalized (i.e.,
templatized) copy constructor is missing the part that
declares the template parameter U. The code should look
like this:

template<class T>
template<class U>
inline auto_ptr<T>::auto_ptr(auto_ptr<U>& rhs)
: pointee(rhs.release())
{}

Scott
--------------------------------------
Check out the *new* "THE C++ Seminar"
http://www.gotw.ca/cpp_seminar/

Thursday, March 7, 2002

My CD and Current Browsers; Leor Zolman's STL Error Decryptor

Two topics:
- Status of Effective C++ CD with contemporary browsers.
- Plug for Leor Zolman's STL decryptor -- and for Leor.


The Effective C++ CD and Contemporary Web Browsers
--------------------------------------------------

When Addison-Wesley (AW) and I developed the Effective C++ CD in 1998, the
dominant browsers were Internet Explorer 3 (IE3) and Netscape 3 (NS3),
though versions 4 were on the horizon. We developed for IE4 and NS4, and
we claimed in the marketing copy that the CD was compatible with IE4+ and
NS4+. That was true through versions 5, but in versions 6 of their
browsers, both IE and NS broke backwards compatibility, and the result is
that the CD doesn't work properly with IE6 or NS6.

AW has decided not to upgrade the CD for contemporary browsers. I'm
telling you this for two reasons. First, I want to alert you to the fact
that the CD won't work with IE6 or NS6 and there are no plans to fix this,
the marketing copy on the box and at the web site notwithstanding. (AW
will fix the marketing copy, BTW. They have no interest in lying to you.
I wouldn't continue to work with them if they did.)

Second, though fixing the CD may be beyond AW's capabilities and beyond
mine (I'm a C++ guy, not an HTML/CSS/JavaScript etc. guy), it may not be
beyond yours. AW and I both encourage you to develop patches for the CD
that will allow it to be used with current browers, including IE6 and NS6,
of course, but also browsers we never supported, such as Opera. If you
develop such patches and make them publically available, AW and I will
happily publicize them (e.g., link to them from our web sites, maybe
mention them in mailings, etc.). Our only real request is that you make
*patches* available, not complete patched copies of the CD. We'd like to
see the CD usable with current browsers, but we don't want to give the CD
away. I'm hoping you can help us out.

I apologize for the CD failing to work with contemporary browsers. We did
the best we could at the time, and I still think we produced a product to
be proud of. If you or people you know could make it possible for the CD
to be used with the latest browsers, that would make me prouder still.


Leor Zolman's STL Error Message Decryptor, etc.
-----------------------------------------------

Leor Zolman checked all the code in Effective STL before the book was
published, and he makes that code available to you at
http://www.bdsoft.com/resources/estlcode.html. In a backhanded kind of
way, however, I'm sort of responsible for his much more significant
accomplishment, because attendance at an offering of my introductory STL
course (http://www.aristeia.com/eistl/index_frames.html) inspired him to
develop a set of perl scripts to make STL error messages a lot more
readable. For example, in Item 49 of ESTL I show this error message:

example.cpp(17) : error C2440: 'initializing' : cannot convert from 'class
std::_Treestd::basic_string,class
std::allocator >,struct
std::pair,class
std::allocator > const ,class std::basic_stringstd::char_traits,class std::allocator > >,struct std::mapstd::basic_string,class
std::allocator >,class
std::basic_string,class
std::allocator >,struct
std::less,class
std::allocator > >,class std::allocatorstd::basic_stringstd::char_traits,class std::allocator > > >::_Kfn,struct
std::lessstd::basic_string,class
std::allocator > >,class
std::allocatorstd::char_traits,class
std::allocator > > >::const_iterator' to 'class std::_Treestd::basic_string,class
std::allocator >,struct
std::pair,class
std::allocator > const ,class std::basic_stringstd::char_traits,class std::allocator > >,struct std::mapstd::basic_string,class
std::allocator >,class
std::basic_string,class
std::allocator >,struct
std::less,class
std::allocator > >,class std::allocatorstd::basic_stringstd::char_traits,class std::allocator > > >::_Kfn,struct
std::lessstd::basic_string,class
std::allocator > >,class
std::allocatorstd::char_traits,class
std::allocator > > >::iterator'
No constructor could take the source type, or constructor overload resolution
was
ambiguous

Here's the same compiler output run through Leor's filter:

example.cpp(17): error C2440: 'initializing': cannot convert from
'map::const_iter' to 'map::iter' No
constructor could take the source type, or constructor overload resolution
was ambiguous

Better, no? Leor's filter(s) are freely downloadable and work with lots of
compilers and libraries (e.g., VC6-7, g++, Comeau, STLport). They can be
used from the command line or as an integrated part of the MSVC IDE. I use
them all the time, and I encourage you to try them, too. You'll find them
at http://www.bdsoft.com/tools/stlfilt.html.

As long as you're at Leor's web site, check out his training courses,
including the one called "An Effective Introduction to the STL." As you
can see at http://www.aristeia.com/training_frames.html, that's my course
:-) Leor is one of the few people I trust to teach it in my place. If
you're looking to have somebody come in and teach the STL to you or your
colleagues, I really think you should give Leor a look, especially if
you're in the Boston area. (In the interest of full disclosure, I'll point
out that if Leor teaches my course, I get a rental fee for the use of my
teaching materials. At least I'm supposed to...)

Scott
--------------------------------------
Check out the *new* "THE C++ Seminar"
http://www.gotw.ca/cpp_seminar/

Sunday, February 24, 2002

Upcoming Appearances

This mailing is all about upcoming appearances:
- March 4-6: Tutorials for the SPC in Vancouver, BC
- March 18-20: TCS2 in Boston, MA
- July 16: Keynote at the RW User Conference in Vail, CO

March 4-6 in Vancouver
----------------------
The Software Productivity Center (http://www.spc.ca/) is sponsoring two
seminars of mine. On March 4, I'll present my one-day course on maximizing
efficiency in C++. Details are available at
http://www.spc.ca/training/public/highperfc.htm. The next two days I'll be
presenting material from "Effective STL." Details are available at
http://www.spc.ca/training/public/effectivestl.htm, but unfortunately, the
details the SPC published aren't entirely accurate (though I hope they will
correct them in the next day or so). What you need to know is this: there
is no overlap in content between the efficiency course and the STL course,
so if you're interested in learning as much about using the STL as you can,
I encourage you to sign up for both courses.

Traditionally, my seminars at the SPC are pretty small (almost always under
30 people, often under 20), so these are a good chance to see me talk about
C++ in a setting where you can ask lots of questions and get plenty of
personal attention.

I apologize for the late notice of these talks (they're barely a week
away), but I hope to see you in Vancouver!


March 18-20 in Boston
---------------------
"THE C++ Seminar II" is rapidly approaching, and that means that I finally
got one of my talks done. My presentation on library design continues to
exist only in my head, but I now know exactly what I'll be talking about in
my Odds and Ends presentation. Here's the text from my overview slide:
- Templates, redundancy, default type parameters, and total specialization.
- PODs, non-PODs, arrays, and an efficiency benchmark.
- Four designs for reference counting smart pointer templates.
- spell, ispell, DWIM, and lint.
- Recommended reading
Kind of eclectic, I know, but what did you expect from a talk on odds and
ends? The recommended reading is fairly extensive, because I was
desperately looking for a way to shoehorn more material into the talk, so I
decided to include thumbnail sketches of things I didn't have time to talk
about along with pointers to places where you can get the full story.


July 16 in Vail
---------------
Rogue Wave has asked me to give a keynote address at their User Conference,
so I'll be presenting thoughts on succeeding with C++ in the real world.
You can read about the talk at
http://www.roguewave.com/corp/events/userconference/featuredspeakers.cfm,
though you'll have to scroll down beyond Bjarne to get to me.


As always, you can find a complete list of scheduled appearances at my
Seminars page, http://www.aristeia.com/seminars_frames.html.

The last few months have been busy ones, so I'll have a couple of
announcements on other topics soon. In the meantime, I hope to see you in
Vancouver next week, in Boston in mid-March, and/or in Vail in July.

Scott
--------------------------------------
Check out the *new* "THE C++ Seminar"
http://www.gotw.ca/cpp_seminar/

Friday, January 11, 2002

Schedule for TCS2; October CUJ Article Now Online

The following things are now available online:
- The schedule and presentation summary for Boston's
"THE C++ Seminar" in March
- My October CUJ article, "STL Algorithms vs. Hand-Written Loops"


THE C++ Seminar
---------------

Astonishingly, Herb Sutter, Andrei Alexandrescu, Steve Dewhurst, Dan Saks,
and I pretty much all managed to get our acts together enough to come up
with titles and descriptions for the talks we'll be giving at our second
"THE C++ Seminar" (aka "TCS2") in Boston in March. The full slate of
presentations is available at http://www.gotw.ca/cpp_seminar/02/index.htm.
(You'll probably have to scoll down a bit to get to the schedule.) I'll be
giving two talks so new, I haven't written them yet! Ahem. But in my head
they're really good. Click on over to the TCS2 page to read about them.

Regarding TCS2, I have a minor correction to the message I sent out on
December 19. In that message, I said that all the talks at the seminar
would be brand new -- never given before in public. This is accurate for
me, Herb, Andrei, and Steve, but Dan has decided to reprise one of the
talks he gave at TCS1, "Making New Friends." This was a jaw-dropper the
first time he gave it, and I suspect it'll drop more jaws this time. If
you haven't seen it, you want to. For his other presentation, Dan has
craftily refused to reveal anything about it, including whether it contains
material he's given in other public presentations. Of course, the four of
us other speakers are now convinced that Dan is preparing a killer talk
that will make the rest of us look like rank amateurs...


October CUJ Article
-------------------

The kind folks at C/C++ User's Journal have now put my October article,
"STL Algorithms vs. Hand-Written Loops" online at
http://www.cuj.com/reference/articles/2001/0110/0110b/0110b.htm?topic=reference.
This article is an excerpt from Effective STL.

Scott
--------------------------------------
Check out the *new* "THE C++ Seminar"
http://www.gotw.ca/cpp_seminar/

Tuesday, January 1, 2002

Updated Errata Lists

As part of my transition-to-a-new-year housecleaning, I've updated the
errata lists for all of my publications:

Effective C++ http://www.aristeia.com/BookErrata/ec++2e-errata.html
More Effective C++ http://www.aristeia.com/BookErrata/mec++-errata.html
Effective STL http://www.aristeia.com/BookErrata/estl1e-errata.html
Effective C++ CD http://www.aristeia.com/BookErrata/cd1e-errata.html

These lists are now comprehensive: all the bugs I know about are in those
lists.

In an ongoing effort to make this mailing list worth subscribing to, I've
listed all the new errata entries below. This mailing list is the only way
to see incremental changes to the errata lists.

Happy New Year!

Scott



EFFECTIVE C++, SECOND EDITION

DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
11/10/01 sdm xiii Change all URLs and email addresses that mention
xv awl.com to URLs/email addresses at aristeia.com
xvi because, despite over six years of trying, the
237 web morons at AW are incapable of maintaining
valid URLs and email addresses.

9/21/01 pxm 6-7 I should clarify that operator+ is assumed to be
a friend of String, hence has access to
String::data.

7/ 6/01 ga Items Include exception specs for operator new. This
7-8 would make parts of these Items easier to
follow. On the other hand, if I use exception
specs here, I'd need to use them in Items 9-10,
too, and also on operator delete and possibly
elsewhere. The book currently uses almost no
exception specs, and perhaps it is more
consistent that way.

7/ 6/01 ga 51 Regarding the para after the first code
fragment, the place pointed to by a and c will
actually be deleted three times, because it will
already have been deleted when b went out of
scope.

7/ 6/01 ga 63-64 The word "twist" is repeated within a short
range. Reword.

7/ 6/01 ga 64 "freestanding functions" ==> "actual
functions in the object code"

7/ 6/01 ga 182 Another common synonym for layering is
"aggregation".

10/17/01 js 202 In the first para, the phrase "begs the question"
is improperly used. Reword.

7/ 6/01 ga 203 In last sentence "PersonInfo::name" ==>
"PersonInfo::theName".

! 7/ 6/01 ga 226 In 2nd to last para, "string" isn't a template,
it's a typedef for a template. Reword.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
7/ 3/01 jcj Item 1 Regarding the argument that using a macro to represent a
floating point literal (such as on page 13) is more space-
efficient than using a const object, jcj writes:

The [const] form is at least as efficient as the #define
because when the preprocessor replaces ASPECT_RATIO with
1.653 in one's source code, that value must be stored
somewhere in the binary machine code. Clearly the fact
that one has a floating-point literal, in addition to the
fact that I can think of no machines that have any
instructions that take floating-point immediates, it is
quite obvious that 99.9% of the time 1.653 will occupy
some typically 64-bit space in memory that will be loaded
and used just like a constant would. In fact, when you
realize that the preprocessor and the compiler may not be
very tightly coupled, the #define form would define a
floating point literal at every point ASPECT_RATIO is
used, where the const form would only have one instance in
memory no matter how many uses there are. When you have
consts that refer to types that may be allowed as
immediates in the instruction set of the compiler, it is
possible that the #define could be faster if the compiler
did not optimize in the same way, but in general I'd be
more worried about 50 floating-point literals peppered
throughout my code than 1 constant used 50 times.

9/10/01 lz 98 If you are using a library with a const-incorrect function
prototype such as that for strlen on this page, there is a
solution better than using a cast at every point in the
program where you call the incorrectly-declared function:
write a wrapper function to perform the cast, then call the
wrapper. In the example on this page, the wrapper function
would look like this:
inline strlen(const char *s)
{ return strlen(const_cast(s); }

================================================================================

MORE EFFECTIVE C++

DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
11/10/01 sdm 8 Change all URLs and email addresses that mention
287 awlcom to URLs/email addresses at aristeia.com
because, despite over six years of trying, the
web morons at AW are incapable of maintaining
valid URLs and email addresses.

12/20/01 pd 11 Wording similar to the following is better for
the final paragraph on this page:

References, then, are the feature of choice
when you know you have something to refer to
and when you'll never want to refer to
anything else. They are also to be used when
implementing operators whose syntactic
requirements make the use of pointers
undesirable. In all other cases, stick with
pointers.

10/ 1/01 jfn 56 In the last sentence before the code example at
the bottom of the page, "private static member
function" ==> "private member function". This
is what I hope is the final undo for the
incorrect "correction" I added on 10/4/99;
consult em's correction reported on 1/1/00 for
details.

! 12/ 5/01 at 63 The first line of prose on this page is
incorrect; section 15.1/5 of the Standard makes
clear that implementations may optimize away the
creation of a separate exception object:

If the use of the temporary object can be
eliminated without changing the meaning of the
program except for the execution of
constructors and destructors associated with
the use of the temporary object (12.2), then
the exception in the handler can be
initialized directly with the argument of the
throw expression.

However, my remark that a catch block couldn't
modify localWidget continues to be true, as does
my observation that throwing an exception is
typically much slower than passing a parameter.

3/12/01 wds 120 Bad hyphenation in 2nd-to-last para: "runt-ime"
==> "run-time".

! 3/22/01 wcm 209 RCPtr and RCIPtr behave inconsistently with
210 respect to automatically performing COW on
pointee objects. The fundamental problem is that
my fix for we's bug report of 3/4/96 above was
incorrect, and I should have realized that when I
had to "bend" the notion of constness to
implement it. As Andrei Alexandrescu noted in
his Modern C++ Design,

Smart pointer are not the best place to
implement COW, because smart pointers cannot
differentiate between calls to const and
non-const member functions of the pointee
object. (Page 165)

The responsibility for triggering COW thus rests
on smart pointer clients, and this is precisely
what I do in the non-const String::operator[] on
page 207 (note the creation of a new StringValue
object). In responding to we's bug report, I
shouldn't have modified RCIPtr. Instead, I
should have modified RCWidget::doThis to call
value->makeCopy before calling value->doThis.
That's what I'll do now, and I'll update the Item
29 source code, too.

9/22/01 sdm 222 Bad justification of last line on page.

! 10/10/01 pb 272 Notes pb, "'extern "C"' doesn't mean that name
mangling is suppressed. Rather, it means that names
should be mangled in the way that the targetted C
compiler mangles them. Some C compilers put an
underscore at the front of a name; others put an
underscore at the end; some don't change the name at
all. A name declared as 'extern "C"' should be
mangled in the same way."

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
11/24/01 iw Item 7 As it turns out, it is possible to overload the ||
and &&
operators while still preserving their short-circuit
semantics, and this is not uncommon in libraries based on
template metaprogramming. Because my objection to
overloading these operators is based on the loss of
short-circuit semantics, I don't oppose libraries that
overload them as long as they also preserve their
short-circuitedness. For an example of a library that
overloads them for good reason, check out the href="http://www.oonumerics.org/tmpw01/jarvi.pdf">Lambda Library
described at the href="http://www.oonumerics.org/tmpw01/schedule.html">Proceedings of the 2001
Workshop on C++
Template Programming
. (iw wasn't the only person to
send me the essence of this comment, but his email was the
one that inspired me to add it to the errata list.)

9/23/01 lz Item 21 One drawback to lots of overloading is that it can lead to
ambiguities. For example, if you declare both f(int) and
f(long) and a client calls f with a char or a double, the
call will be ambiguous until the client casts the char or
double to an int or long.

================================================================================

EFFECTIVE STL

DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
9/26/01 kh 13 The definition of contiguous-memory containers
should say that such containers are assumed to
store more than one element per dynamically
allocated chunk of memory; they are not
required to do so. In theory, both deque and
string could be implemented as arrays of pointers
to objects, for example, though no sane imple-
mentation would do things that way. (Very large
objects may be stored only one element per chunk
of memory in a deque, though one would have to
wonder why such large objects were being stored
in an STL container in the first place.)

! 11/ 5/01 sdm 61 In 2nd-to-last para, the claim that C++
guarantees that local objects are destroyed if
an exception is thrown is not quite true. The
guarantee holds only if the exception is caught.

9/27/01 lz 77 In the second section of example code, the call
to vd.resize(...) is missing the final closing
parenthesis.

! 11/ 5/01 ma 134 In last code example, "widgets.begin()+20" should
be "widgets.begin()+19".

11/ 5/01 sdm 111 In 2nd-to-last line of Item 24, "map" should be
in code font.

11/18/01 sk 160 PointAverage's constructor should list its member
initializers in the order in which the data
members are defined in the class. (Shame on me
for making this mistake, as it is the topic of
Item 13 in my href="http://www.awl.com/cseng/titles/0-201-92488-9/">Effective
C++
.)

12/26/01 jdl 211 In 2nd para, "I uses" ==> "I use".

! 10/ 4/01 rd 207 The comment above the initialization of rangeBegin
is incorrect. It should read as follows:
Initialize rangeBegin to point to the element
following the last occurrence of a value greater
than or equal to y. If there is no such value,
initialize rangeBegin to v.begin(). If the last
occurrence of the value is the last element in v,
initialize rangeBegin to v.end().

11/10/01 sdm 225 Change all URLs and email addresses that mention
228 awl.com to URLs/email addresses at aristeia.com
because, despite over six years of trying, the
web morons at AW are incapable of maintaining
valid URLs and email addresses.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
9/24/01 mm Item 1 Sometimes, the best data structure for a problem is not in
the STL at all. mm writes that "One of the biggest misuses
that I've seen of the STL is when maps are used instead of
sparse matrix data structures. ... In many applications, a
matrix is very sparse. It is often the case that there is
just 2 to 5 entries per column, even in matrices with tens
of thousands of rows. ... There are highly efficient data
structures for doing this, and they're not very
complicated. ... There are lots of efficient algorithms
available for doing all sorts of operations on a matrix,
and there are various places on the internet (especially
www.netlib.org) that
have classes that encapsulate this."

12/22/01 sdm 37-39 Windows programmers experimenting with my
DeleteObject class should beware that there is a
Windows function with the same name. (I didn't know
what when I wrote the book.)

11/14/01 axg Item 10 One way to avoid creating allocators with per-object state
is to declare all member functions static.

11/ 5/01 sdm 60-61 An alternative to creating and using the Lock template is
to use href="http://www.cuj.com/experts/1812/alexandr.htm">Alexandrescu's and
Marginean's ScopeGuard
technique
.

11/13/01 ib 60-62 Given that manual concurrency control is a necessity, you
might consider using href="http://www.boost.org/libs/thread/doc/index.html">the cross-platform
threading library
available at Boost
.

11/12/01 sdm Item 25 Regarding the choice of basing hashed containers on
equality or equivalence, P. J. Plauger, founder of
Dinkumware, posted this to comp.lang.c++.moderated on
8/27/01:

Our latest version of the hash template classes aims for
the best of both worlds. Turns out it can hash properly
given either a strict weak ordering, as in operator
less<T>, or an inequality comparison, as in
operator
not_equal<T>. So we add a partial specialization
that
looks for SGI-style template parameters and invert the
sense of the supplied predicate. The upshot is that you
can use our hash tables as a drop-in replacement for
map/set, using a strict weak ordering, or as a drop-in
replacement for SGI-style hash_map/set, using an
(in)equality comparison.

If you're interested in the choice between equality and
equivalence for hashed containers, you might want to
href="http://groups.google.com/groups?hl=en&threadm=998828578.794072%40news.aei.\
ca&rnum=1&prev=/groups%3Fhl%3Den%26selm%3D998828578.794072%2540news.aei.ca">view
the thread from which this posting is taken
.

11/14/01 yd 243-244 yd writes: "I took your advice and turned on the
__STL_MEMBER_TEMPLATES flag in the SGI STL
configuration. However I was not able to compile, due to a
Microsoft bug (Q241949 in the MS knowledge base). MSVC6
supports member templates, but only when they are defined
inside the class body. The SGI STL has many such members
defined out-of-body. Getting it to compile would require
extensive cut-and-paste throughout. I haven't checked
STLport, but chances are it has the same problem since
it's derived from SGI STL."
I know from personal experience that some constructs
requiring member templates work with MSVC6 and STLport, so
this suggests that STLport has modified the SGI
distribution on which it is based to better work with
MSVC6. That suggests that STLport's STL may be a better
choice than SGI's, at least as regards support for member
function templates under MSVC6.

================================================================================

EFFECTIVE C++ CD

DATE DATE
REPORTED WHO WHAT FIXED
-------- --- ------------------------------------------------------- --------
9/18/01 dp The CD doesn't work properly with IE6, e.g., image and
chunk size choices don't appear in the navigation area,
and lines don't break to fit the browser window.
+---------------------------------------------------+
| Check out the *new* "THE C++ Seminar" |
| http://www.gotw.ca/cpp_seminar/ |
+---------------------------------------------------+

Wednesday, December 19, 2001

TCS2; Talks at Software Development

Two topics this time:
- An all-new "THE C++ Seminar" will take place in Boston in March.
- I'll be giving four talks at Software Development in San Jose in April.

TCS2 (THE C++ Seminar 2)
------------------------

The initial "THE C++ Seminar" was so successful and so much fun, we decided
to do it again, this time in Boston in March. (If you're not familiar with
"THE C++ Seminar", you can read about the idea behind it at
http://groups.yahoo.com/group/scott_meyers/message/17 and can get detailed
information about it at http://www.gotw.ca/cpp_seminar/)

There is an important difference between the seminar we held in October and
the one we'll host in March: virtually all of the material will be new.
Really new. So new, it's never been presented before any any public forum
and has never appeared in a book or magazine article. (At least not one we
wrote.) That means that if you attended TCS1 or have read every word we've
ever published, you can sign up for TCS2 without fear of seeing the same
tired stuff you've seen before. (We may decide to repeat a couple of the
panel sessions we did at TCS1, but all of the individual talks will be new,
and I'm pushing to avoid panel repeats, too.)

You'll find general TCS information at http://www.gotw.ca/cpp_seminar/.
Registration information for TCS2 is at
http://www.gotw.ca/cpp_seminar/02/index.htm. A discounted "early bird"
registration fee applies until the end of January. I encourage you to
register early, because TCS1 was nearly sold out by the end of its early
bird period.


Software Development
--------------------

I'll be speaking at the Software Development Conference
(http://www.sdexpo.com/) again this year. I'm giving three C++ talks:

STL Allocators
Maximizing STL Performance
C++ Odds and Ends

I'm also giving a keynote address that is about software development in
general (as opposed to specifically about C++):

The Keyhole Problem and its Many Kin

You can find descriptions of all of these talks at
http://cmp.bluedot.com/re/attendee/wsw_02/speakerPage.esp?speakerId=36633866

Regarding the conference, the SD bigwigs have asked me to let you know the
following:

We have a special offer for any attendees whom you refer to SD West
2002. If they use the code 2WSPKR, they will receive $300 off any
multi-day pass with no expiration date!

An offer like that kind of takes your breath away, doesn't it?

I hope everybody is having a happy holiday season, and I hope to see you in
Boston in March, in San Jose in April, or both.

Scott

Tuesday, October 30, 2001

ESTL Errata List has been Updated

In preparation for the upcoming third printing of Effective STL, I've
fully updated the ESTL Errata list, including the addition of a number of
new bug reports and "interesting comments." My raw notes for the latest
delta are below, but things got massaged a fair amount as I integrated the
new material into the old list, so don't be surprised when you find
differences between what's below and what's in the list at
http://www.aristeia.com/BookErrata/estl1e-errata_frames.html.

My favorite bug in the book so far, though not one of the new ones below,
is the one reported for page 126, where I and every one of my pre-pub
reviewers overlooked the fact that in several places on the page, I'd
written "operator<<" where I clearly meant "operator>>". When reading the
manuscript, each of us saw what we wanted to see -- what we *expected* to
see -- instead of what was actually on the page. I marveled when that was
reported. But not right away. First I had to read the report over several
times. It look that long for my eyes to see that what was in ink was not
what was in my brain.

Scott


[Raw notes for latest ESTL errata update]

DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
9/ 4/01 bww iv Change "Meyer, Scott" to "Meyers, Scott" in the
Library of Congress Cataloging-in-Publication
Data.

10/ 4/01 ap 47 In 1st para, clarify that erase's return value
is void in associative containers only for the
forms taking iterators. (When passed a value,
erase returns the number of elements erased.)

10/24/01 wg 66 The first sentence of the third paragraph begins,
"Given all that ..., It should not". The word
"it" is errantly capitalized.

10/11/01 gn 67 In second and third bullets, the parameters
taken by resize and reserve are of type
Container::size_type, not size_t (though for all
the standard containers, Container::size_type
must be size_t).

10/11/01 gn 67 In second bullet, it is worth noting that there
is also a two-argument version of resize, the
second argument specifying the value to copy
into new elements if the container needs to be
increased in size.

8/22/01 jep 68 At end of 2nd-to-last para of Item 14, note that
any use of push_back would invalidate an
end iterator, e.g., one initialized from s.end().

! 10/11/01 gn 99 In the long middle para, casting away the
constness of a map key doesn't yield undefined
behavior, but attempting to MODIFY the key
does.

8/22/01 jep 100 Step 5 says that giving an accurate hint to the
"hint" form of insert yields constant-time
complexity, but it actually yields amortized
constant time complexity. Fixing this requires
that I also modify page 6 to define "amortized
constant time," and I'll have to add the term to
the index, too.

8/22/01 jep 104 In the 4th comment from the top of the page, the
reference to Item 45 should really be to Item 19.

8/22/01 jep 110 As in jep's bug report for page 100 above,
insertion with a hint yields amortized constant
time complexity, not simply constant time.

10/11/01 gn 118 In first line of second bullet, "const iterator"
==> "const_iterator". The latter should be
in code font.

8/22/01 jep 118-9 The Standardization Committee appears to be on
the verge of officially deciding that
comparisons between iterators and
const_iterators should always compile. For
details, consult href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#179">Library
Working Group Issue
#179
. While you're there, note the link to
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#280">Issue
#280
, where you'll see that whether to
require comparisons of reverse_iterators and
const_reverse_iterators is not yet resolved.

! 8/22/01 jep Item 27 The code shown in this Item is sanctioned by
the Standard for every standard container except
string, and it should also work for any string
implementation that avoids reference counting.
For strings using reference counting, calling
begin() may invalidate existing iterators, and
that leads to this problem:

typedef string::iterator Iter;
typedef string::const_iterator ConstIter;

string s;
ConstIter ci;
... // make ci point into s

Iter i(s.begin()); // calling begin
// invalidates ci!

advance(i, distance(i, ci));
// pass invalidated ci
// to distance

A use of advance and distance that should work
with any standard container c (including strings
employing reference counting) is this:

Container::difference_type d =
distance(c.begin(), ci);
Iter i(c.begin()); // invalidates ci, but we
// don't need it any more
advance(i, d);

9/21/01 fk 136 At the top of the page, begin and end should
probably be declared const. (In fact, I should
probably look at all the code examples in the
book to see if other local vars could be
declared const, too.)

! 8/22/01 jep 159 In the second call to accumulate on this page,
1.0 should be 1.0f. The comment should also be
adjusted, as should the sentence after the example.

9/ 8/01 dxc Item 23 This Item focuses on lookup time, but overall
performance is determined by both setup time
(including the time to sort the vector) and lookup
time. Clarify that the assumption underlying this
Item is that the number of lookups vastly dominates
the number of insertions and erasures.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
10/11/01 gn 33 Regarding the declaration of the function int f(double(d))
at the bottom of the page, the text suggest that the
parentheses are ignored. Well, it depends on what d is. If
it is a type-name then the function is
int f(double (*)(d)), and that is not the same as
int f(double d). The d must be looked up in this case to
determine if it is a type-name or not. See 8.2/7.

typedef int d;
int f(double(d)); // d is a type-name =>
// int f(double (*)(int));

int d;
int f(double(d)); // d isn't a type-name =>
// int f(double);

10/11/01 gn 53 Though the book is correct that the type of the allocator
for ListNodes is

Allocator::rebind::other

you'd have to express that type like this in a program:

typename Allocator::template rebind::other

Pages 7-8 explain why the "typename" is necessary, and the
use of "template" here is similarly required to help the
parser process things correctly.

8/22/01 jep 66 The "aptly named max_size member function" does nothing
more than return a number based on the number of bits in
size_type. It has nothing to do with how many items may
really be placed in any of the containers without
exceeding memory.

8/22/01 jep 90-91 You don't have to create a functor class, because
you could use stringPtrLess's type, then pass
stringPtrLess as a constructor argument:

bool stringPtrLess (string const*, string const*);
typedef bool (*StringPtrLess) (string const*,
string const*);
set ssp(stringPtrLess);

This is legal code, but I consider it highly ill-advised,
because it allows for the possibility that you have
multiple containers of the same type but with
different
sort orders. To me, that's a recipe for disaster, and
that's why I went out of my way to avoid mentioning it in
the book.


8/22/01 jep Item 21 Using less_equal is even worse than you say. The average
quicksort used in sort will crash with some data sets.
Neither 10A nor 10B will be in the range of equal_range.
For { 9 10B 10A 11 } I got find(10) is end,
lower_bound(10) is 11, upper_bound(10) is 10B, and
equal_range(10) is [11, 10B), an invalid range.

9/21/01 fk Item 37 fk points out that the accumulate approach to computing
the average of a set of points involves multiple
divisions, while the for_each approach does only a single
division at the end. As a result, he suggests that the
for_each approach may be more accurate. This seems likely
to me. At any rate, it's all but certain that for some
sets of points, the accumulate and for_each approaches
will yield slightly different averages due to the
complexities of floating point math.

10/14/01 kg Item 37 There is a notable difference between the accumulate and
the for_each approaches to this problem. When the range
is empty, accumulate returns Point(0,0), but calling
result on the functor returned from for_each yields
undefined behavior due to division by zero.

Tuesday, September 18, 2001

Registration for THE C++ Seminar Reopened

Last week's terrorist attack forced us to postpone THE C++ Seminar, which
was orignally scheduled for this week. The new dates are October 15-17,
and if there's anything that can be considered "good" about the
postponement, it's that we were able to reserve a room that can accommodate
more people this time. After existing registrants are given a chance to
roll over their registrations and people from the wait list are given a
chance to enroll, there are likely to be a dozen or so empty slots. If you
are interested in being able to participate in a hard-core C++ seminar with
me, Herb Sutter, Dan Saks, Steve Dewhurst, and Andrei Alexandrescu, I
encourage you to visit the seminar's home page
(http://www.gotw.ca/cpp_seminar/) to view the schedule and details on how
to register.

I hope to see you at the seminar, where I can promise a certain amount of
fireworks as I attempt to convince my head-in-the-sand compatriots that
namespaces, templates, and exceptions aren't necessarily all they're
cracked up to be...

Scott

Friday, September 14, 2001

Updated errata lists; article in CUJ; upcoming seminar reports

Topics this time:
- EC++ and MEC++ Errata Lists have been updated.
- I have an article in the October CUJ.
- Reports from "THE C++ Seminar" to be posted (but not here).


Updated Errata Lists:

I just finished updating the errata lists for Effective C++ and More
Effective C++. (Both books are due for reprints later this month, so the
time was ripe.) New entries to the errata lists are at the end of this
message. The full lists are available at the usual URLs:

EC++: http://www.aristeia.com/BookErrata/ec++2e-errata_frames.html
MEC++: http://www.aristeia.com/BookErrata/mec++-errata_frames.html


Article in the October CUJ:

The October CUJ contains a slightly-modified version of Effective STL's
Item 43, "Prefer Algorithm Calls to Hand-Written Loops." (The article
title is one of the things that is slightly modified compared to the book.)
As an aside, the December CUJ is slated to run ESTL Item 45, but don't
believe it until you see it, because publication plans have been known to
change at the last minute.


Reports from "THE C++ Seminar":

The special C++ Seminar hosted by me, Herb Sutter, Dan Saks, Steve
Dewhurst, and Andrei Alexandrescu runs next Monday-Wednesday. If you're
one of the people who would have liked to attend, but couldn't, or if
you're just curious about what such an event will be like (I am), we plan
to post daily informal summaries to the seminar's mailing list. (They will
NOT be posted to this list). You can sign up for the seminar's mailing
list at http://groups.yahoo.com/group/cpp_seminar/.


Finally, I truly hope that you and yours were not personally affected by
Tuesday's indescribable horrors. Words do not exist for how I feel, so
I'll just say this: I wish you all the best.

Scott

===============================================================================
New Entries for the EC++ Errata List
===============================================================================
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
3/ 7/01 das xix "Dave Smallberg" ==> "David Smallberg" 9/10/01
254

! 8/25/00 pm 68 In operator=, "*ptr = *rhs.ptr;" ==> 9/10/01
"ptr = rhs.ptr;" Modify the comment
accordingly.

8/15/00 cb 104 Eliminate the first prose paragraph on this page. 9/10/01
105 (When I originally wrote the paragraph for the
first edition of EC++, the example involved
string objects, not rational numbers, and for
strings, the situation was different. When I
changed the class for the example, I failed to
recognize that the words no longer made sense
for the example.) To avoid too unbalanced a
page, I moved the break between pages 104 and 105.

8/16/00 cb 124 At the end of the 2nd to last sentence on the 9/10/01
page, it would be helpful to xref Item 21's
explanation that the data pointed to by a pointer
in a const object is not automatically const.

! 2/10/00 ic 212 A class declaring no operator& function(s) 9/10/01
cxh 213 does NOT have them implicitly declared. Rather,
245 compilers use the built-in address-of operator
246 whenever "&" is applied to an object of that
type. This behavior, in turn, is technically
not an application of a global operator&
function. Rather, it is a use of a built-in
operator.
I eliminated mention of operator& as an
automatically generated function and adjusted the
index to eliminate entries for the removed
material.

! 4/ 8/01 hs 228 The Standardization Committee has now ruled that 9/10/01
library implementers must declare string as
defined in the Standard, so my comment about
their being allowed to add extra parameters is
incorrect. However, the Standard continues
to forbid you from declaring string yourself.
The advice in this Item stands (#include
<string> instead of trying to declare the string
type yourself), but the rationale for that
advice is no longer valid.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
8/ 8/00 cb 15 Observes cb:

It appears that the Microsoft Visual C++ 6.0 SP3 compiler
requires the "enum hack" to work. Interesting, since it
is stated that "Unless you're dealing with compilers of
primarily historical interest (i.e., those written before
1995), you shouldn't have to use the enum hack."

It appears that Visual C++ 6 was released in mid-1998.
Sigh.

6/20/01 cbs Items cbs points out that the code in Item 30 isn't thread safe,
sdm 7,8,10 but the problem exists in Items 8 and 10, too. In fact, I
fail to consider thread-safety throughout the book,
something I can argue is excusable only because C++ itself
fails to consider threading issues. You'll see other
comments on how threading interact with my advice in
various places in this errata list. If I ever write a
third edition, I'll be sure to take threading issues into
account.

6/ 5/01 sdm 67 In the prose following the third code example, it's not
technically true that the temporary is const. Rather, the
temporary is an rvalue, and C++ forbids binding references
to rvalues unless they are references to const. This is
not a bug in the book. Rather, it is a deliberate attempt
to spare you from having to know about rvalues, because
they're more confusing than helpful, especially if you know
the rules for rvalues in C. Setting aside technicalities,
the information on this page is accurate in its
essentials.

6/22/01 sdm Item 19 The bulleted summary at the end of this Item no longer
reflects my full thinking on this topic. For an updated
version of the summary as well as an explanation of how and
why things changed, please read my February 2000 href="http://www.cuj.com/" target="_top">C/C++
Users Journal
article, href="http://www.cuj.com/articles/2000/0002/0002c/0002c.htm" target="_top">"How
non-member functions improve
encapsulation
."

2/19/01 sdm Item 19 When templates enter the picture, things become more
complicated. Compilers must not only perform type
conversions on actual parameters, they must also perform
template type deduction to determine the types of formal
parameters. The end result is that templates for functions
like operator+ should still be non-members, but they need
to be defined as friends inside the class they work with in
order to be instantiated correctly. For details, consult
the February 2000 thread in comp.std.c++ with the title,
href="http://groups.google.com/groups?hl=en&safe=off&threadm=zdv176.950799804%40\
zam475&rnum=1&prev=/groups%3Fas_epq%3Dautomatic%2520conversion%2520with%2520func\
tion%2520templates%26as_ugroup%3Dcomp.std.c%252b%252b%26as_drrb%3Db%26as_mind%3D\
29%26as_minm%3D1%26as_miny%3D2000%26as_maxd%3D5%26as_maxm%3D9%26as_maxy%3D2001%2\
6num%3D100" target="_top">"Automatic conversion with function templates?"

It was
initiated by Bernd Mohr.

9/17/00 ch Item 20 Notes ch:

Objects are state machines. An Object would lose control
of its own states if you allow public data members. This
makes it for instance impossible to implement a typical
Observer Pattern in an object oriented way. The problems
get really nasty for objects with public data members
when living in a multithreaded environment ....

6/11/00 tm 99 In general, it's dangerous for a function to return a
reference to a parameter passed by reference-to-const,
because the parameter may have been bound to a temporary
object that will be destroyed at the end of the call. For
example, consider this use of returnStudent:

Student makeStudent(); // function declaration

const Student& cs = returnStudent(makeStudent());

returnStudent's parameter s is bound to the temporary
object returned from makeStudent. returnStudent then
returns that reference, which is used to initialize another
reference, cs. Unfortunately, once cs is initialized, the
temporary returned from makeStudent is destroyed, and cs is
a dangling reference -- it refers to an object that no
longer exists. (Note the similarity to the problem
discussed on pages 127-128.)

2/27/01 ph Item 23 Once you've resigned yourself to returning a new object
from functions like operator*, you'll naturally look for
ways to make that as cheap as possible. One way to do that
is to return a pointer posing as an object.
The following comment was sent regarding Item 20 of href="http://www.awl.com/cseng/titles/0-201-63371-X/" target="_blank">More
Effective C++
, but it's relevant to Item 23 of
Effective
C++
, too:

We faced the problem of getting large float and int
arrays from a database. The dimension of the array
depended on the time interval passed as an argument to
the reading method. Clearly, we had to return an object,
and we couldn't rely upon return value optimization
[which is the subject of MEC++ Item 20].

Our solution was to return an auto_ptr<Array<T>
> instead
of an Array<T>. This way, we had the advantage of
returning something as light as a pointer without the
problem of potential memory leaks. The only drawback was
a slightly heavier syntax but it was worth it.

I don't think this is a solution for the method operator*
that you used in item 20 but many other methods that have
to return large objects may benefit from it.


===============================================================================
New Entries for the MEC++ Errata List
===============================================================================
DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
3/30/01 sdm 2 Material in the book is based on the final C++
Standard, not the DIS.

9/ 6/00 bp 33 In accord with my advice in Item 21 of Effective
C++ to "use const whenever possible," oldValue
should be declared const in the code example at
the top of the page.

2/21/01 wds 58 In second paragraph, "initializationof" ==>
"initialization of".

! 8/15/00 wcm 142 For consistency with the changes I made on
144 6/6/98 (see above), the Counted template should
have objectCount return a size_t instead of an int,
and numObjects should be of type size_t, not int.

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
7/31/00 cw 208ff Notes cw:

While href="http://www.aristeia.com/BookErrata/M29Source.html"
target="_blank">exploring your reference counting code
, I realized
that there is no method allowing a user of the RCIPtr
class to mark the CountHolder unshareable. I believe such
a method is essential to the correct operation of the
RCIPtr when a user is confronted with making a some one
else's class reference counted and that class has methods
which return references to the the internal parts of the
class.

In your widget example, if there were a method
int& Widget::getThat(), the corresponding RCWidget method
would have to make a call to a RCIPtr::markUnshareable()
method that would call the RCObject::markUnshareable()
method. This would prevent the int reference from being
used to alter a widget that is held by more than one
RCWidget.
http://www.aristeia.com/BookErrata/M29Source.html

2/27/01 ph Item 20 Writes ph:

We faced the problem of getting large float and int
arrays from a database. The dimension of the array
depended on the time interval passed as an argument to
the reading method. Clearly, we had to return an object,
and we couldn't rely upon return value optimization.

Our solution was to return an auto_ptr<Array<T>
> instead
of an Array<T>. This way, we had the advantage of
returning something as light as a pointer without the
problem of potential memory leaks. The only drawback was
a slightly heavier syntax but it was worth it.

I don't think this is a solution for the method operator*
that you used in item 20 but many other methods that have
to return large objects may benefit from it.


4/27/97 sdm Item 30 In a posting to comp.lang.c++.moderated posting of
4/25/97, Brian Parker writes:

One problem with the use of proxies that I have found that
is not discussed in "More Effective C++" is when they are
used for templated types e.g. for complex... . In
this scenario, when calling template functions that take
complex (e.g. conj() et al) with a returned proxy, the
proxy is not converted to a complex but instead a
template argument deduction failure results.

For further information on this observation, look up the
thread, href="http://groups.google.com/groups?hl=en&threadm=5jq51o%2479g%40netlab.cs.rpi\
.edu&rnum=1&prev=/groups%3Fas_epq%3Done%2520problem%2520with%2520the%2520use%252\
0of%2520proxies%26as_ugroup%3Dcomp.lang.c%252b%252b.moderated%26as_drrb%3Db%26as\
_mind%3D29%26as_minm%3D3%26as_miny%3D1997%26as_maxd%3D13%26as_maxm%3D9%26as_maxy\
%3D1997">"lvalue/rvalue, non-const/const"
initiated by Daniel
Hempel on April 21, 1997.

8/ 5/01 sdm Item 31 For a more contemporary treatment of multiple dispatch
than I give in Item 31, check out chapter 11 of Andrei
Alexandrescu's excellent href="http://www.awl.com/cseng/titles/0-201-70431-5/">Modern C++
Design
. It's the most
thorough and up-to-date examination of the topic that I know
of.

Monday, September 3, 2001

Updated ESTL Errata; Powell's Talk Reminder

Two quick things:
- I've updated the ESTL errata list. New entries are below.
- Reminder: I'm speaking at Powells in Portland this Thursday.

Updated ESTL Errata List:

I've received a number of interesting bug reports and other comments on
ESTL since I last updated the errata list, so I've added the new stuff to
the list. You'll find the updated list in its usual spot at
http://www.aristeia.com/BookErrata/estl1e-errata_frames.html. The new
entries are listed below in the half-baked form I use internally for
keeping track of new errata.


Talk at Powell's this Thursday:

This Thursday night I'll be doing a C++/STL Q&A at Powell's Technical
bookstore at 7:00 PM. For details, consult my earlier mailing on this
topic (http://groups.yahoo.com/group/scott_meyers/message/27). I hope to
see you there!


Scott


DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
8/31/01 ds iv "Dr. Suess" ==> "Dr. Seuss" (twice).

8/ 4/01 dg 18-19 Once the typedef WidgetContainer is introduced,
the variable vw should be renamed cw to reflect
the new, more abstract, type name.

8/23/01 sdm Item 4 Clarify that of the three list::splice functions,
only one requires linear complexity. The other
two can run in constant time and can allow size to
run in constant time.

8/17/01 sdm 47 Omit from para 2 the advice to treat list like
a sequence container. Based on a discussion with
jep, I'm now less certain that that convention is
as widespread as I'd thought.

! 8/16/01 kh 55-56 My discussion of putting containers in shared
memory is incomplete and, to some degree,
misleading. As Item 15 demonstrates, some string
implementations use the small string optimization,
so elements of such strings won't be in shared
memory unless the string objects themselves are.
Furthermore, even use of placement new to put
containers in shared memory won't put static
components of those containers in shared memory,
and the Standard allows containers to have such
components (e.g., a shared empty string
representation); some implementations take
advantage of this allowance. kh summarizes things
this way: "No matter how well-written your
allocator implementation [for shared memory], if
it works, it is either a matter of luck or
hardwiring to a specific container implementation."

! 8/23/01 ja 78-79 When string implementations use reference
counting, the swap trick doesn't decrease the
capacity, because the copy constructor isn't
allocating any memory; it's just adjusting a
reference count. A more reliable way to perform
shrink-to-fit is to create the temporary string
via the range constructor, e.g., like this for the
last line of code on page 78:
string(s.begin(), s.end()).swap(s);

8/23/01 ja 79 The last paragraph of Item 17 is true, but it
doesn't matter in this context, because the swap
is with a temporary object that is destroyed at
the end of the statement. As a result, all
iterators, pointers, and references into the
"shrunk-to-fit" string have been invalidated.
I'll omit this paragraph from future printings
(and I'll try to remember to check the index to
see if it gets anything from this paragaph).

7/31/01 gl Item 20 When your comparison function for an associative
container isn't less<T>, it's important to specify
the comparison function for all algorithms that
will perform comparisons. Include a warning in
this Item and xref the example on pg. 149 in
Item 34. Note that following the advice of Item 44
minimizes the chances of running into this kind of
problem.

! 8/22/01 sdm 92 Eliminate the second-to-last sentence on this
page. In fact, equal values *are* equivalent,
because neither of two equal values precedes the
other in any reasonable sort order. (The
definition of "reasonable" is "strict weak
ordering," as I mention on page 94.)

! 8/22/01 jep Item 22 Shortly after the book was published, the Committee
decided that elements of sets/multisets should not be
modifiable without a cast, so the second code example
on page 96 is now invalid. To change a set/multiset
element in place, use the const_cast technique shown
on page 98. If you don't need in-place modification,
the five-step process described on pp. 99-100
continues to be safe and portable.

! 8/22/01 jep 104 In the lines after the calls to lower_bound, the
106 second test should be "!(w < *i)" and
"!(s < i->first)", respectively. This needs to be
fixed in both the code and the comments.

! 8/20/01 ag 108 The analysis for the cost of the call to insert is
incorrect, because it overlooks that the pair
created in the insert call is a temporary that
will ultimately be used to copy construct the pair
stored in the map. Because the temporary pair
contains a Widget, a temporary Widget is
constructed and destroyed. In practice, ag
observed that "the difference between the two
methods is only that in the operator[] form,
there's the extra call to the assignment operator
specialized for a double."
ag has demonstrated that operator[] could be
implemented much more efficiently than insert, but
the Standard is unfortunately worded in a way that
makes such implementations illegal. In the
future, this wording may be changed, or
implementers may choose to ignore it.
All things considered, the conclusion that insert
is more efficient than operator[] when adding new
elements to a map is not as reliable as I thought
when I wrote the book. In the immortal words of
Nathan Myers, "if it matters, measure."

8/ 4/01 dg 136 In last para, "which reorders element" ==>
"which reorders elements".

8/23/01 sdm 144 In the lower diagram, non-code text in
"remove_if's return value" should be in text font.

! 8/16/01 kh 159 In the call to accumulate at the top of the page,
the literal 0 is incorrect. Because its type is
int, accumulate will use int as its internal type
for storing the partially accumulated sums. The
correct type for this is string::size_type. It
makes a difference, because int is signed and
string::size_type is unsigned.

8/ 3/01 sdm 160 In the para following the code, there should be
no line break between "paragraph" and "2".

8/ 4/01 dg 162 The use of the term "components" in the 1st para
is confusing, because I never define that term.
Reword. (In general, I use "component" in this
book to mean "something in the STL.")

8/21/01 sdm 165 BPFCImpl should inherit from unary_function.

8/24/01 sdm 169 Practically speaking, anotherBadPredicate isn't as
bad as the function objects generated by
BadPredicate, because there is only one copy of
its state. As a result, anotherBadPredicate is
likely to behave as expected when passed to
remove_if or any other algorithm. (But see below
for "Interesting Comments" on Item 39.)

8/18/01 sp 187 Once in a code example on each page,
188 "vector<int> iterator" ==>
189 "vector<int>::iterator".

8/23/01 sdm 200 In the entry for equal_range in the next-to-last
row of the table, add "(followed by distance)".
Make the same change to this table on the book's
inside front cover.

8/30/01 ab 211 At end of 2nd para, "Another STL platform I uses..."
==>
"Another STL platform I use..."

8/ 4/01 dg 221 In 2nd para, "do fire up" ==> "do is fire up".

8/28/01 jtw 228 A more reliable URL for [27] is
http://www.research.att.com\
/~bs/stack_cat.pdf
.


Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
7/28/01 jep Item 9 The approach I show for erasing elements in a contiguous-
memory container while iterating through it does a good
job of maintaining iterator validity, but the time
complexity of the approach is quadratic. This can
typically be improved to linear by using a two pass
strategy:
1. Walk the container, writing the log for each element
you plan to erase (but don't erase anything yet).
2. Perform a range erase, e.g., by using the erase-
remove idiom or by using partition (or
stable_partition) and then erasing.

8/19/01 hxh 72-73 Regarding Implementation B's capacity being 7 when the
size of the string is 5, hxh (the author of
Implementation B) writes:

At the time I wrote , I could not imagine an
allocator that could deliver a non multiple of
sizeof(void*) bytes on the platforms I was targeting. I
could imagine specialty allocators that could very
efficiently deliver 4 bytes, but not 1, 2 or 3 bytes.
Or 8 bytes, but probably not 5, 6 or 7. So string takes
advantage of this. If the client asks for 5 bytes, he
gets 7 (8 minus 1 for the terminating null). So this
string really does have a minimum capacity. It's 3. I
tend to go for very small minimum capacities in order to
make containers of containers more efficient.

8/ 4/01 sdm Item 23 As part of the Loki library described in his book,
Modern
C++ Design
(Addison-Wesley, 2001), and downloadable
from the book's web site, Andrei Alexandrescu developed the
AssocVector template, a map-like container built on top of
sorted vectors. If you're interested in the performance
improvements you might get from using a sorted vector
instead of a map, consider downloading AssocVector and
giving it a try.

8/20/01 ag 110-111 Write ag:

The discussion about using a generic ValueArgType to use
the specialized assign if present is interesting, but
using KeyArgType instead of key_type may trigger
multiple conversions for the key. Imagine having a map
indexed by strings and calling

efficientAddOrUpdate(m,"Andrea",10.5);

With the version in the book there are three conversions
from KeyArgType to key_value: one in lower_bound, one in
key_comp and another one in insert.

8/ 3/01 yjz Item 37 Writes yjz:

I agree that accumulate most clearly expresses what's
going on. Personally, that's more intuitive to me. I
would definitely choose accumulate when I do simple
value accumulations. But for the final example in this
item, I would definitely use for_each because the
solution using accumulate provided by this item
introduces a lot of overhead by calculating the average
point every time the operator() is called. So,
supposedly, we have n elements in the container, for the
example using accumulate, you will calculate the average
of points n times. But in for_each example, you only do
that calculation once. For this specific example, there
are 2*(n-1) times of division and (n-1) times of
construction of temporary Point objects which are not
necessary.

8/24/01 sdm Item 39 My decision to advise readers to make predicates pure
functions was based on pragmatic considerations, not on
the Standard. In fact, Kreft and Langer argue in their
April
2001 CUJ column
that the Standard allows
predicates to have state, though they concede that the
problem I describe in this Item does exist in some STL
implementations. The Committee is aware of the problem,
but from what I can tell, they are leaning towards
modifying the Standard to require that predicates be pure
functions. If they do, my advice will conform to the
Standard at that point. To follow the Committee's
deliberations on this matter, monitor the status of
Library
Working Group Issue #92
.

6/16/01 al Item 39 The idea of using remove_if to eliminate the third element
from a range is misguided. Implicit in my discussion is
the idea that remove_if will examine the elements in the
range FROM THE BEGINNING TO THE END, but this is not
required by the Standard and conceptually doesn't make
sense. Even if the predicate passed to remove_if could
safely have state, the only thing we could reasonably
expect from remove_if is that the third element visited
would be removed; we wouldn't be able to make any
assumptions about WHICH element that would be. For more
on this idea, consult the April 2001 column by
Klaus Kreft and Angelika Langer, "Unary
Predicates
in the STL."
At the same time, it's worth noting that
every implementation of remove_if I know behaves like the
one in the book, and there are technical reasons why
alternative implementations are unlikely.

8/16/01 kh 203 Strictly speaking, the code at the bottom of this page
is not standard-conformant, because library implementers
are permitted to add extra parameters to library
functions, as long as the parameters have default
values. (You can read about this matter in Herb
Sutter's GOTW
#64
.) A workaround for such a perverse
library implementation would be precisely what Item 46
suggests: use a function object to wrap the call to the
library function.

Tuesday, August 21, 2001

Appearance Sept. 6th in Portland, Oregon

Addison-Wesley has scheduled me for an "author event" in Portland, Oregon:

Powells Technical Bookstore
33 NW Park
Portland, Oregon

Thursday, September 6
7:00 PM

This will be an open-ended Q&A session on anything in my books, my
articles, my newsgroup postings, or anything else in the world of C++. Or
my dog. In case there are no questions for me, I'll bring questions for
you :-)

I hope to see you September 6th at Powell's in Portland.

Scott

Friday, August 3, 2001

June CUJ Article is now Online

My June CUJ article, "Three Guidelines for Effective Iterator Usage," is
now available in PDF at my web site:
http://www.aristeia.com/Papers/CUJ_June_2001.pdf.

Scott

Monday, July 30, 2001

Updated ESTL and CD Errata Lists

I've just posted updated errata lists for Effective STL and the Effective
C++ CD. You'll find the updated lists at the usual places:

ESTL: http://www.aristeia.com/BookErrata/estl1e-errata_frames.html
EC++CD: http://www.aristeia.com/BookErrata/cd1e-errata_frames.html

The list for the CD hasn't changed much. The list for ESTL has.

I hope to update the errata lists for Effective C++ and More Effective C++
later this month.

Scott

Tuesday, July 17, 2001

Last call for "THE C++ Seminar"

"THE C++ Seminar" (http://www.gotw.ca/cpp_seminar/) featuring me, Herb
Sutter, Dan Saks, Andrei Alexandrescu, and Steve Dewhurst sells out at 85
attendees. There are now about 10 spots left, and we can't increase the
limit, because the hotel has no more room. (I know, because I called them
today.)

If you've been thinking about attending the seminar, I encourage you
to register immediately.

Thanks,

Scott
+---------------------------------------------------+
| Check out THE C++ Seminar: 3 Days with 5 Experts |
| http://www.gotw.ca/cpp_seminar/ |
+---------------------------------------------------+

Wednesday, June 27, 2001

First ESTL Errata; InformIT Sale on my Books

Two things:
- First ESTL Errata list.
- 35% off on my books at InformIT.


ESTL ERRATA LIST
================

I'm pleased to report that ESTL is already up for a second printing, giving
rise to the possibility that Amazon will finally stock enough copies to
avoid having to list the book's availability as "usually ships in 4-6
weeks." Grumble. Sometime this summer I'll find the time to post the
changes to the ESTL errata page, but until then, here's a mailing list
exclusive: a sneak preview of the first list of ESTL errata and
"interesting comments." Some of the formatting is a little odd, because
it's semi-ready to be dropped into an HTML document.

DATE DATE
REPORTED WHO PAGES WHAT FIXED
-------- --- ----- ------------------------------------------------ --------
5/ 9/01 sdm Many In most places where I mention arrays, I should
mention valarrays, too. Like vectors, valarrays
are constrained to have contiguous storage, and
this means that pointers can be used as iterators
into valarrays.

6/21/01 jw 136 In the last comment in the code example, 6/21/01
"goalPosition now points" ==>
"begin + goalOffset now points"

6/26/01 mjh 164 "containing lot of data" ==> "containing lots 6/21/01
of data"

5/ 7/01 sdm 228 Add to [26] that the article and the software it 6/21/01
describes can be downloaded from
http://www.bdsoft.com/tools/stlfilt.html.

6/26/01 dp 228 URLs for both columns by Matt Austern ([24] and 6/21/01
the second bullet after [27]) end in .htm, not
.html. (I checked all the URLs shortly before
publication, so these must have changed right
after the book was initially printed.)

Interesting Comments:

DATE
REPORTED WHO PAGES WHAT
-------- --- ----- -----------------------------------------------------------
6/22/01 lz Many Thanks to Leor Zolman, all the code fragments in the
book are available in compilable form at
http://www.bdsoft.com/resources/estlcode.html.

5/ 8/01 sdm Many STLport debug mode is no longer the only STL
implementation where vector's and string's iterators
aren't real pointers. The latest Dinkumware library
(including the one shipped with VC .NET) also uses
classes for these iterator types.

6/20/01 cc 93 Writes cc:

The comparison type StringPtrGreater can be
implemented in terms of comparison type StringPtrLess:

struct StringPtrLess:
binary_function
{
bool operator()(const string* ps1, const string* ps2)
const
{ return *ps1 < *ps2; } }; struct StringPtrGreater: binary_function
{
bool operator()(const string* ps1, const string* ps2)
const
{ return StringPtrLess()(ps2, ps1); }
};

Not only does this ease the maintenance, but also,
more importantly, expresses the logic: To determine if
x > y, we just need to test if y <> a are necessary and sufficient
conditions for each other.

If we want a pair of generic dereferencing less and
greater functor class instead of StringPtrLess and
StringPtrGreater, we can do the same:

template
struct dereference_less: std::binary_function
{
bool operator()(const T* p1, const T* p2) const
{ return *p1 < *p2; } }; template
struct dereference_greater: std::binary_function
{
bool operator()(const T* p1, const T* p2) const
{ return dereference_less()(p2, p1); }
};

6/18/01 sdm Item 31 Additional useful information on the STL's various
sorting options can be found in Matt Austern's
column in the August 2001 CUJ, "Sorting in the
Standard Library,"
http://www.cuj.com/experts/1908/austern.htm.

6/16/01 al Item 39 The technical information in this Item is correct, but
the idea of using remove_if to eliminate every third
element from a range is fundamentally misguided.
Implicit in my discussion is the idea that remove_if
will examine the elements in the range FROM THE
BEGINNING TO THE END, but this is not required by the
standard and conceptually doesn't really make sense.
Even if the predicate passed to remove_if could safely
have state, the only thing we could reasonably expect
from remove_if is that ONE THIRD of the elements in
the range would be removed; we wouldn't be able to
make any assumptions about WHICH elements would be
removed. For more on this idea, consult the April
2001 column by Klaus Kreft and Angelika Langer, "Unary
Predicates in the STL,"
http://www.cuj.com/experts/1904/langer.htm. At the
same time, it's worth noting that every implementation
of remove I know behaves like the one in the book, and
there are reasons why alternative implementations are
unlikely. In practice, then, the discussion in Item
39 is accurate. Still, its underlying conceptual
validity is flawed.


INFORMIT SALE ON MY BOOKS
=========================

InformIT is offering 35% off on all three of my C++ books until July 13.
This is the same discount I get as an author, and it's better than anything
BestBookBuys.com could find. This is from the InformIT newsletter I was
recently sent:

Bonus! For a limited time only, InformIT offers 35% off
the following Scott Meyers titles in the Book Store;
"Effective C++," "More Effective C++," and "Effective STL."

Find 35% savings on Scott's books at:

Effective C++
http://www.informit.com/newsletter.asp?link=614

More Effective C++
http://www.informit.com/newsletter.asp?link=615

Effective STL
http://www.informit.com/newsletter.asp?link=616

Remember, you need n+2 copies of each of my books, where n is the number of
cars you have. That's one copy for home, one for the office, and one for
each car -- for when you're stuck in traffic :-)

Scott
+---------------------------------------------------+
Check out THE C++ Seminar: 3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar/
+---------------------------------------------------+

Saturday, June 16, 2001

Error in Seminar Dates; Free ESTL for past Seminar Attendees

Two very quick things:
- I got the Zurich seminar dates wrong.
- Attendees of my earlier STL seminars get a free copy of ESTL.

In my last mailing, I bungled the dates for my seminar in Zurich. The
correct dates are at my web site. Rather than run the risk of getting them
wrong here again, here's the link to my seminars page:
http://www.aristeia.com/seminars_frames.html. I apologize for the error.

If you attended one of my STL seminars last June or this past January,
you're entitled to a free autographed copy of ESTL. If you haven't
received email recently asking for your current mailing address, it's
because our email to you bounced, and we don't know how to get in touch
with you. If you were a seminar attendee and you haven't heard from us,
please send your current mailing address to nancy@.... That's my
wife, so be nice to her :-)

Scott
+---------------------------------------------------+
| Check out THE C++ Seminar: 3 Days with 5 Experts |
| http://www.gotw.ca/cpp_seminar/ |
+---------------------------------------------------+

Upcoming Seminars in Europe and Japan; ESTL Sale

Two topics:
- Seminars scheduled for Zurich, Stuttgart, Berlin, and Tokyo
- ESTL on sale at 40% off


SEMINARS

I've recently scheduled fall seminars in Switzerland, Germany, and Japan.
In particular:
Zurich, Switzerland September 17-19
Stuttgart, Germany September 24-25
Berlin, Germany October 1-2 and 4-5
Tokyo, Japan November 13-16
You'll find details at my seminars page,
http://www.aristeia.com/seminars_frames.html. At that same page you'll
find a link to "THE C++ Seminar," which I mentioned in an earlier mailing.
The more we work on it, the better I think that seminar is going to be.
It's currently about 1/3 subscribed, so if you're interested in attending
(and I hope you are), I encourage you to register sooner than later.


EFFECTIVE STL ON SALE

Both Amazon.com and BooksAMillion.com are currently offering Effective STL
for $24, which is 40% off. As an author, my discount when buying the book
is only 35%, so I think this is a pretty good deal! If you've been
thinking about buying the book, I think this is a good opportunity to get
it for cheap. To preview the content in ESTL, check out my article in the
June C/C++ User's Journal as well as the four sample Items you'll find at
AW's site for the book, http://www.aw.com/cseng/titles/0-201-74962-9/.

If you decide to buy the book from Amazon, please consider going to Amazon
via the following link, because I get a small kickback if you do. (Your
price remains unchanged.)


http://www.amazon.com/exec/obidos/ASIN/0201749629/o/qid=987984055/sr=2-2/scottme\
yersho-20

Thanks,

Scott
+---------------------------------------------------+
| Check out THE C++ Seminar: 3 Days with 5 Experts |
| http://www.gotw.ca/cpp_seminar/ |
+---------------------------------------------------+