[cfe-dev] on libc++ extensions and slist

Chandler Carruth chandlerc at google.com
Sun Jul 31 16:13:29 PDT 2011

On Sat, Jul 30, 2011 at 6:31 PM, Howard Hinnant <hhinnant at apple.com> wrote:

> In existing C++03 standard libraries there are a ton of extensions.  Some
> good, some not so good.  Some of the better ones have morphed into official
>  C++11 libraries.  However, I can't think of a single example where an
> extension has been standardized unchanged from its extension form.  There is
> good reason for this.
> I'm going to pick on slist.  But my argument is meant to be broader than
> slist.


I want to clarify, I don't disagree with *any* of your diagnosis. I agree
completely with the flaws and problems present in slist.

> When our customers are migrating to libc++, it is at a time of their
> choosing.  They have set aside time to do the migration.  And shown interest
> in doing so.  A year after they migrate, when subtle problems surface, they
> are not going to be in the mood to be educated.  They are going to be in the
> mood to be educated about the right way to do things *when they are
> migrating*, and not later when run time problems arise.

Keep in mind that some customers at least may not be able to update all of
their code in one fell swoop. Forcing changes to the client code in too many
places may make it impossible to migrate at all rather than merely adding to
the cost of migration.

Also, in some contexts, there is no user education to be done. The code in
question is legacy code, old and slated for deletion. No one maintains it,
updates it, or cares for it; but it isn't (quite) ready to be removed once
and for all. These situations make the arguments about education only apply
to a subset of the migration (although there they certainly make sense).

> 1.  We could create an ext::slist that lacks size().  That way the customer
> would not have to change their code unless they used size().

I agree with your disadvantages here. Reducing (slightly) the magnitude of
those changes doesn't seem as attractive. For a significant chunk of the
code I've seen in this position, the cost of changing the code is dominated
by a very high constant factor, not by the nature of the change itself.
(Consider, an open source library that has to have changes pushed back
upstream, and written in a particular style and which no one is actively
maintaining any longer.)

> 2.  Status quo:  We could do nothing.
> Disadvantage:  I'm seeing rising complaints about migration efforts.

There is another disadvantage: it may preclude migration at all. If there
exists code that simply can't be updated, you're now stuck.

More realistically, it may drive the cost of migration sufficiently far up
that it becomes a difficult or impossible to tackle problem.

> 3.  Educate:  In a private email about a week ago M.E. O'Neill noted that
> we should provide documentation recommending migration strategies for things
> like slist -> forward_list.  She suggested actually providing an <slist>
> header which did nothing but point to the documentation and then error out.
>  I'm not sure I'd go as far as providing such a header.  But I am really
> enthusiastic about a "migration document".  Having something to point to
> which explains why using slist is like playing with a loaded gun.  When
> people are migrating, they are open to such arguments if those arguments are
> both convincing and readily available.  And if the migration document
> provides a way to experiment without committing yourself (i.e. make it easy
> to backpedal the migration):

Again, see my points above about education. Sometimes there is no one to
educate, and no one intending to maintain or improve the code long term.
Certainly, documenting the migration hurdles is very helpful to those doing
the migration, but it may not be enough for sufficiently popular extensions.

> Disadvantage:  Doesn't provide seamless migration.  And it is a fair amount
> of work to document.
> Field experience:  I'm responsible for deprecating auto_ptr.  At the same
> time I introduced unique_ptr.  This involved a lot of documentation.  Not
> only with committee papers, but in participating in countless newsgroup and
> mailing posts to the general public, presentations, etc.  And it is paying
> off.  I now see lots of people I've never heard of telling others that they
> should replace auto_ptr with unique_ptr, even though it is not a drop-in
> replacement.  And the listeners are receptive to the message.

I don't really dispute any part of this other than the value of education on
old code. For new code and actively maintained code, this is all spot on.

That said, I would like to migrate a very large codebase to a point where it
could use libc++. Why? Because I want to migrate the codebase to C++0x, and
one aspect of doing that is migrating to a viable standard library for
C++0x. I'm very interested in investigating the trade-offs between libstdc++
and libc++ here, but we can't do that if we have to update the entire code
base in the process.

I actually will pick on hash_{map,set} here because I think they're even
better examples. I actually agree that 'slist' is border-line.

There is essentially zero possibility that we will use hash_map forever. We
will switch to unordered_map because its better and because its
standardized. However, it isn't available (technically[1]) until we switch
to C++0x. With a codebase of sufficiently large size, we can't afford to do
both transitions simultaneously, we have to first switch to C++0x, and then
switch from old extension containers to new standard ones.

[1]: Yes it is available as std::tr1::unordered_map, but now we have to
migrate the codebase 3 times, once to the std::tr1 implementation, once to
0x, and then once back to std::. That drives up the cost of migration by
another notch.

Now, my goal is to have two different libraries to choose from when
migrating to C++0x so that bugs in one don't block progress. But in order to
do that we need at least "enough" extension support in both libraries to
make it tractable to use either one.

This isn't an argument for "all", merely for "enough". For example libc++
already has hash_map and hash_set, and that is probably the single most
important container to support. We've now gotten a trial run conversion of a
non-trivial chunk of our codebase to libc++, and the only other container
that was missing was 'slist'. The only other missing extensions were a
handful of very rarely used algorithms. Algorithms are much easier to work
around than types, as two pieces of code can use different but compatible
implementations without conflicting. I see no reason for libc++ to bother
with these extensions.

The types are trickier. Had there been 10 extension types we needed, making
'slist' a slippery slope of extensions we might never get off of, I would be
more sympathetic to drawing the line sooner and more forcefully. I think the
best argument for adding a compatible 'slist' implementation is that it
seems to be the last we'll need.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110731/f4784ebc/attachment.html>

More information about the cfe-dev mailing list