Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2005-09-06 23:19:35

Thomas Witt <witt_at_[hidden]> writes:

> David Abrahams wrote:
>> Thomas Witt <witt_at_[hidden]> writes:
>>>Thorsten Ottosen wrote:
>>>>My recollection is that having boost::foo() do ADL was *firmly* rejected, and
>>>I think I am at least partially responsible for this. And so far I am
>>>still unconvinced that making a qualified call basically a shortcut for
>>>an unqualified call is a good idea.
>> It's a shortcut for an unqualified call plus a using declaration.
> After reviewing my earlier posts on this topic I still don't believe in
> the proposed resolution(boost_range_begin etc.) and in the specific use
> of customization points in general.

The second half of that sentence sounds rather sweeping and extreme.

> AFAICS the underlying problem is retrofitting an interface to a
> component that is not owned by us.

It me took about 10 re-readings of this email to guess that us == the
library developer and the component is, e.g. a pre-existing component
like std::vector or builtin arrays. Did I get that right?

> The problem usually arises in us being unable to invade the
> components namespace. As for the case at hand
> std::vector<int> v;
> begin(v); // error begin is member of boost not std!
> does not work.


> In order to have our cake and eat it we move our
> interface in our own namespace where we are free to do whatever we
> see fit.

I don't see it that way. If we're using the strategy discussed here
-- which I'm not claiming is ideal -- we do that part just to keep
other authors of generic code from having to remember to write ugly
using declarations.

We move the _implementation_ of the function for those pre-existing
3rd party types into our own namespace where we do anything we want.
In other words, aside from that ugly using declaration, which is
needed to make the interface truly generic, the interface lives in the
"global ADL space." I guess if you view the using declaration as a
kind of namespace qualification, you could see this as moving the
interface into our namespace.

> The problem being that we cannot provide the interface for all types
> out there but we still want this to be extensible. Furtheremore we
> sure don't want anybody to invade our namespace

I don't think we care about that last part, provided they do it in a
way prescribed by us. Certainly, specialization is a kind of
invasion, and that's no problem. The problem becomes that inviting
the user to invade our namespace with _overloads_ just doesn't work
because ordinary lookup is limited to what's visible at the
point-of-definition. As I recently posted for Robert Ramey,

  14.6.4 Dependent name resolution [temp.dep.res]

    In resolving dependent names, names from the following sources are

    â€” Declarations that are visible at the point of definition of the

    â€” Declarations from namespaces associated with the types of the
      function arguments both from the instantiation context
      ( and from the definition context.

which makes overloading in our namespace fragile due to header order

> so we provide an ADL customization point so that other libraries can
> hook into our interface.


> So what does that mean for the other libraries out there? They have
> to clutter their interface with these hooks that are meant only for
> communication with the boost library and that are useless if the
> user of the other library does not use boost.

Not if you buy Peter Dimov's argument that many customization points
become "public domain" and are no longer the property of any library.
Read that part of the thread carefully. Once people start supplying
begin() hooks, other library authors may start making interfaces that
work with Boost.Range compatible types.

> Apart from the fact that the hook strategy is unlikely to scale well
> (how many potentially useless hooks do you want in your library?)

In my library? Useless? I'm confused. Am "I" the author of a
library component who is trying to get it to work with other libraries
like Boost.Range?

Something like begin(x), if I'm the author of a container type, seems
useful to me!

> it also seems to put the burden on the wrong side.

So... the author of Boost.Range should figure out how to get the begin
iterator out of a type he doesn't know about? Who should have the burden?

> In order to make the use of a finite set of types easier we complicate
> the use and design of an infinite set of types.

More confused. Which finite set? Which infinite set?

> There is one more point I like to make. How is the range concept
> going to look like. As far as I can see it will "degrade" to
> something that is only used in the interface between the "public"
> interface that is in boost and the component that wants to expose
> the boost interface.

It might be used by anyone wanting to write composable generic
algorithms over sequences. One of the problems with the STL interface
is that composing the algorithms is more cumbersome than it should be.

Dave Abrahams
Boost Consulting

Boost list run by bdawes at, gregod at, cpdaniel at, john at