Boost logo

Boost :

Subject: Re: [boost] Breaking existing libraries
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2008-11-24 16:53:40


On Mon, Nov 24, 2008 at 10:40 AM, Thorsten Ottosen
<thorsten.ottosen_at_[hidden]> wrote:
> But the change was far from accidental, and was not only motivated by my
> wish to break peoples code (ironi), but came about because users of the
> library had great troubles with the original concepts. We had lengthy
> discussion here on the list. Eric Niebler initiated some of them because
> he was trying to use boost.range in Boost.for_each.

Name one trouble that anyone had with the Range concepts that was
caused by the presence of the empty(r) requirement. The accusation
doesn't make any sense. How did removing empty(r) fix a bug or
implementation or interface issue with Boost.For_each? Was there a
name conflict?!

I mean, look, even if for some reason you did need a Range concept
that didn't require empty(r), the solution is not to deny all types
the ability to model Range concepts that require empty(r). If you need
an even less specific concept of a Range, define a less specific Range
concept. Don't artificially collapse the requirements of richer
concept specifications. By analogy, the fact that the most general
iterator is a SinglePassIterator doesn't mean that we should remove
the additional refinements of the ForwardIterator,
BidirectionalIterator, and RandomAccessIterators. That there is a
minimalist Container concept definition does not mean that we should
remove the refinements that give us AssociativeContainers, etc. If you
needed a Range concept that didn't include empty(r), you should define
the new, less refined Concept, not destroy the more refined Concepts.

> Although you might be of a different opinion, then it was not without
> sensible reason to remove empty() from the concepts. The new concepts are
> much clearer, and let us define empty as boost::empty(r) without imposing
> additional concept requirements.

Concept requirements are not imposing; they are enabling! Without the
empty(r) requirement users are not able to test a range for emptiness
directly in a generic way. In other words, if a function's only type
requirements is that it support the expressions begin(r), end(r) and
empty(r), then it should require that the type model a concept with
these expressions. If the Range concept no longer supports these
expression, then users can no longer write generic functions that
require them.

Removing empty(r) also puts limits on the authors of types modeling
Range. Say you write a type that models Range where the values in the
range are held in a database on the other side of the network. Perhaps
there's a fast way to implement empty(r) if you know something about
the database and/or network topology. However, if empty(r) is not
required by the concept then you can't offer this benefit to users who
writing generic code for any Range based on the definition of the
Range concept. This issue is just going to become more pronounced as
concepts play a more prominent role in C++0x.

> The library changed after its original form, and into something much better.

How is it better to not be able to check for emptiness in a generic way?

> And the change was motivated by real user feedback, something which the
> original review in some sense could not provide as much of.

I'm sure you had feedback regarding iterator_range. However, I
seriously doubt that you received feedback from users demanding that
empty(r) be immediately removed from the definition of the Range
concept. That doesn't make any sense,

Daniel Walker


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk