
"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:usm242h75.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > | > yes, but in return the library only has two provide one overload | > | ^^^-"to" | > | > of begin/end. | > | | > | Meaning that you don't need a separate overload taking Seq const& just | > | to handle mutable rvalues. That's good. However, that benefit | > | doesn't depend on uglification. We could use the same old names; the | > | interface would just not be useful for mutable rvalues unless the 2nd | > | overload were provided. | > | > but now you introduce the ADL lookup problem again. | | What is "the ADL lookup problem?"
the problem that emerges when you want ADL to happen, but cannot use an unqualified call because it would create conflicts between
boost::begin; sequence::begin foo::begin
You have to consider that problem in the context of the question, "how likely is it that there will be no best match among those three?"
| > | Another point is that the whole iterator/const_iterator thing is | > | artificial and broken anyway. My work has evolved towards a "cursors | > | and property maps" arrangement where cursors encode position/traversal | > | and property maps encode access. In that scheme there's no difference | > | between the cursors used when traversing constant and mutable | > | containers. Of course, if you want to be able to get read access to a | > | non-const property map rvalue you may need two overloads for that | > | purpose. | > | > How would I traverse a range in that framework? | | It depends whether the cursors are homogeneous (like iterators, the | usual case) or heterogeneous (a different type at each position).
so heterogeneous means "compile-time" iteration?
Hybrid runtime/compile-time iteration. Generally it means full unrolling of any loop.
| The latter requires a recursive formulation; I won't go into it | here because it's not really relevant to what we're discussing. | The former looks like: | | end_cursor<S>::type finish; | for (begin_cursor<S>::type p = sequence::begin(s); p != finish; ++p) | ... | | In either case, elements are accessed via: | | elements_type<S>::type e = sequence::elements(s); // the property map | value_type<S>::type v = e(p); // read | e(p,v); // write
if e is a "map", then why dont you allow e[p] and e[p] = v ?
I allow it; I just don't require it ;-) Function call syntax is good for interoperability (e.g. using Boost.Bind). This insight is Doug Gregor's contribution. Using [] for current Boost property maps was probably a mistake. Writing to property maps via e[p] = v requires reference proxies in some cases, which is just unnecessary complication.
| > | We need to decide whether we're going to accept sub-optimal | > | designs or not. If we want to use standard iterators (for which | > | there are obvious positive arguments) we are forced into some | > | compromises that we wouldn't have to accept if using cursors, | > | > How does ADL lookup change in the new framework you're working on? | ^ ^^^^^^----- redundant ;-)
redundant? you will use the existing iterators as cursors then?
I mean that "_A_rgument _D_ependent _L_ookup lookup" is redundant. ^^^^^^^^^^^^^^^ But yeah, in some cases I may use the existing iterators as cursors.
| Only that sequences will be providing begin(s) and not | uglified_begin(s). I was going with "uglified" names like | sequence_begin() until I thought harder about Thomas' argument and | considered the likelihood of bad collisions to be low.
it could fairly easily happen IMO. more and more code is put into header files qualified syntax hence becomes more important
Show me a realistic example, please. I am still in the early stages and can change this element of the design if necessary.
| > I don't see how it relates to the the proposed changes to | > boost.range which has as its main purpose to enable ADL lookup while | > using qualified notation. | | It's related to the argument that you only have to provide one | overload of begin/end.
right, so it doesn't solve what I called "the ADL lookup problem".
I'm not sure there's as much of a problem there as you're making out.
| > | Shouldn't a Boost.Range-conformant range type be usable without the | > | dispatching functions in Boost.Range? | > | > well, for vector<int> v; you can use v.begin() etc. for pair<I,I> p, you | > can use p.first etc. | | And what about a new range type that someone invents? Should they | really pick a different interface and not use something like the one | Boost.Range already provides for its ranges?
So assume don't want to use boost.Range. They can use what ever syntax they want and call their functions
namespace foo { iterator begin( X& ); }
Assume they later want to use boost.range, just provide a simple overload
namespace foo { iterator range_begin( X& r ) { return ::foo::begin(r); } }
Right, but now they're just adding redundant interface. Why not just use begin to start with?
| > So I don't think that makes much sense; boost.range is a | > framework---either you use it or you don't. | | I repeat, go back and read Peter's posts in http://tinyurl.com/55j7b. | The framework ceases to own its concepts eventually.
Was it the concept it its customizarion points?
No comprende.
I recall it as it was the costumization points that a framework ceases to own.
The customization points and their expected semantics are what make up the Range concept's requirements.
begin() is a bad customization point
I'm not sure of that anymore. Conflicts caused by GCC can be misleading. And now that we know how to properly isolate types to prevent unintended ADL, I think it's even less of a problem. -- Dave Abrahams Boost Consulting www.boost-consulting.com