
Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
The second half of that sentence sounds rather sweeping and extreme.
Please don't read to much into it. It's just that I have serious doubts.
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?
Sorry for not being more clear. You are basically right. Us means boost or boost::range in particular.
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.
I would not want to describe using declarations as ugly. They clearly describe the intent of the programmer.
Yes, at a very low level. That's sort of like saying that node<T>* n = new node<T>(x, &mylist.front()); mylist.set_head_ptr(n); clearly expresses the intent of the programmer. IMO mylist.push_front(x); is a lot clearer and more expressive.
Though I do agree that forgetting about them is a very likely cause of error.
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."
The point that I am concerned with is _which_ interface adds up in the "global ADL space". IIUC the ADL hooks boost_range_begin etc. end up there. AFAICS these are not meant to be used by a user of a library, are they?
Unfortunately, no. But what can you do when such a major compiler as GCC makes it impossible to use a simpler name without stomping on another Boost library?
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.
I was talking about functions like begin(), end() those end up in the boost namespace, don't they.
Yeah, they sure do, and -- at least from one valid perspective -- appropriately so. The begin semantics you're interested in when you call boost::begin(x) are those that have been defined by Boost.Range, and not some other idea of what "begin" means. I've been consulting with some very smart quant guys this week in a Swiss bank, and when we talked about the fact that swap has become blessed as a global ADL customization point they got very worried, because in the financial world, "swap" has a very different meaning.
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.
I've read through his argument at least twice in the past. That being said I might still not get the point. I do agree with the names becomming public domain. What I disagree with is that names like boost_range_begin are suitable for this.
What should the name be?
They will likely always be warts in an interface.
Why do you think of them as part of the interface, if, as you say, they're not intended to be used directly by end-users? The fact that they appear in the header file, or even in the same namespace with public interface elements, doesn't automatically make them interface elements. To be an interface element, a function must be documented as such. These hooks have the same role as a class template specialization in the library namespace would.
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?
Just assume you are.
Well, it's not useless if it makes my component work with BOOST_FOREACH. So I still don't understand your question.
Something like begin(x), if I'm the author of a container type, seems useful to me!
Yes begin() but not boost_range_begin()
Something that allows generic code to use my class as a range doesn't seem useless to me either.
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.
I am all for a range concept. I am at odds with the proposed solution for that.
Clearly. All I'm hearing from you are complaints, without a proposal for an alternative that works. The problem of building customization points for generic C++ libraries has no really satisfying solution at the moment. Any approach we choose will be a compromise. It isn't clear to me why this particular compromise should be deemed worse than any of the others. -- Dave Abrahams Boost Consulting www.boost-consulting.com