[range] breaking changes

Dear all, Have anybody any last objections to breaking changes to boost.range: boost::range_iterator<T>::type becomes boost::range::iterator<T>::type and so forth. All code that relies on ADL inside the range library by overloading the functions begin() etc will need to be renamed range_begin() etc. br -Thorsten -- Thorsten Ottosen ---------------------------- www.dezide.com http://www.cs.aau.dk/index2.php?content=Research/mi www.boost.org www.open-std.org/JTC1/SC22/WG21/

Thorsten Ottosen wrote:
Dear all,
Have anybody any last objections to breaking changes to boost.range:
boost::range_iterator<T>::type
becomes
boost::range::iterator<T>::type
and so forth. All code that relies on ADL inside the range library by overloading the functions begin() etc will need to be renamed range_begin() etc.
Sorry I was unresponsive for a few days but I was travelling. I still think this is the wrong way to do it. One reason is that it requires every library X that wants to interface with the range lib to uglify its interface by the range_ prefix. AFAICS there are two ways out of this a) X provides the unprefixed begin as well. b) X requires the use of boost.range in order to have a "natural" interface I really think this is bad. If we want to have adl wrappers these should carry the prefixes. What did I miss? Thomas -- Thomas Witt witt@acm.org

"Thomas Witt" <witt@acm.org> wrote in message news:d2rt3p$g1b$1@sea.gmane.org... | Thorsten Ottosen wrote: | > Dear all, | > | > Have anybody any last objections to breaking changes to boost.range: | > | > boost::range_iterator<T>::type | > | > becomes | > | > boost::range::iterator<T>::type | > | > and so forth. All code that relies on | > ADL inside the range library by overloading the functions begin() etc | > will need to be renamed range_begin() etc. | | Sorry I was unresponsive for a few days but I was travelling. I still | think this is the wrong way to do it. One reason is that it requires | every library X that wants to interface with the range lib to uglify its | interface by the range_ prefix. yes, but in return the library only has two provide one overload of begin/end. |AFAICS there are two ways out of this | | a) X provides the unprefixed begin as well. how does that solve anything? | b) X requires the use of boost.range in order to have a "natural" interface | | I really think this is bad. a) or b) ? | If we want to have adl wrappers what is an ADL wrapper? -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"Thomas Witt" <witt@acm.org> wrote in message news:d2rt3p$g1b$1@sea.gmane.org... | Thorsten Ottosen wrote: | > Dear all, | > | > Have anybody any last objections to breaking changes to boost.range: | > | > boost::range_iterator<T>::type | > | > becomes | > | > boost::range::iterator<T>::type | > | > and so forth. All code that relies on | > ADL inside the range library by overloading the functions begin() etc | > will need to be renamed range_begin() etc. | | Sorry I was unresponsive for a few days but I was travelling. I still | think this is the wrong way to do it. One reason is that it requires | every library X that wants to interface with the range lib to uglify its | interface by the range_ prefix.
Thomas makes a good point.
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. 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. 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, and I think, Thomas, that you'll have to accept that there's not really any completely satisfying solution in C++03.
|AFAICS there are two ways out of this | | a) X provides the unprefixed begin as well.
how does that solve anything?
It allows clients of X to use it without boost.range. Go back and read Peter Dimov's posts in this thread: http://tinyurl.com/55j7b (http://news.gmane.org/find-root.php?message_id=%3c004801c522aa%24ee97fd10%24...). Shouldn't a Boost.Range-conformant range type be usable without the dispatching functions in Boost.Range?
| b) X requires the use of boost.range in order to have a "natural" interface | | I really think this is bad.
a) or b) ?
I'm pretty sure Thomas means that either one is bad. We aren't left with any good choices.
| If we want to have adl wrappers
what is an ADL wrapper?
template <class T> typename iterator<T>::type begin(T& x) { using somebody's::range_begin; return range_begin(x); } Also known as a dispatching function. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:ull7wga9b.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > "Thomas Witt" <witt@acm.org> wrote in message | > news:d2rt3p$g1b$1@sea.gmane.org... | > | Thorsten Ottosen wrote: | > | > Dear all, | > | > | > | > Have anybody any last objections to breaking changes to boost.range: | > | > | > | > boost::range_iterator<T>::type | > | > | > | > becomes | > | > | > | > boost::range::iterator<T>::type | > | > | > | > and so forth. All code that relies on | > | > ADL inside the range library by overloading the functions begin() etc | > | > will need to be renamed range_begin() etc. | > | | > | Sorry I was unresponsive for a few days but I was travelling. I still | > | think this is the wrong way to do it. One reason is that it requires | > | every library X that wants to interface with the range lib to uglify its | > | interface by the range_ prefix. | | Thomas makes a good point. hm...I don't think it is particularly ugly compared to so many other hacks. Once a protocol for ADL hooks are provided, it will seem quite natural to users. | > 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. | 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? | 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? 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. | > |AFAICS there are two ways out of this | > | | > | a) X provides the unprefixed begin as well. | > | > how does that solve anything? | | It allows clients of X to use it without boost.range. Go back and | read Peter Dimov's posts in this thread: http://tinyurl.com/55j7b | (http://news.gmane.org/find-root.php?message_id=%3c004801c522aa%24ee97fd10%24...). | 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. So I don't think that makes much sense; boost.range is a framework---either you use it or you don't. | > | If we want to have adl wrappers | > | > what is an ADL wrapper? | | | | template <class T> | typename iterator<T>::type | begin(T& x) | { | using somebody's::range_begin; | return range_begin(x); | } | | Also known as a dispatching function. that's what I figured too. -Thorsten

"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?"
| 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). 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
| 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 ;-)
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.
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.
| > |AFAICS there are two ways out of this | > | | > | a) X provides the unprefixed begin as well. | > | > how does that solve anything? | | It allows clients of X to use it without boost.range. Go back and | read Peter Dimov's posts in this thread: http://tinyurl.com/55j7b | (http://news.gmane.org/find-root.php?message_id=%3c004801c522aa%24ee97fd10%24...). | 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 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. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"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 | > | 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? | 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 ? | > | 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? | 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 | > 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". | > | > |AFAICS there are two ways out of this | > | > | | > | > | a) X provides the unprefixed begin as well. | > | > | > | > how does that solve anything? | > | | > | It allows clients of X to use it without boost.range. Go back and | > | read Peter Dimov's posts in this thread: http://tinyurl.com/55j7b | > | | > (http://news.gmane.org/find-root.php?message_id=%3c004801c522aa%24ee97fd10%24...). | > | 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); } } | > 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?. I recall it as it was the costumization points that a framework ceases to own. begin() is a bad customization point; hence we need two functions. -Thorsten

"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

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1x9nzw3b.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > | 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?" just consider that all of the begin()'s may have an unconstrained primary template version. all three is going to match. | > 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. please consider the example above. | > 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 you mean by namespaces? | to | prevent unintended ADL, I think it's even less of a problem. IMO there is no such thing as unintended ADL during a call to boost::begin(). you always want it. -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1x9nzw3b.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
| > | 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?"
just consider that all of the begin()'s may have an unconstrained primary template version. all three is going to match.
How likely is that? It doesn't seem bery likely to me. foo::begin will almost certainly be more specific. I don't think you mean "primary template," do you? You're not talking about using function template specialization are you?
| > 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.
please consider the example above.
Doesn't seem particularly realistic.
| > 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
you mean by namespaces?
Yes.
| to prevent unintended ADL, I think it's even less of a problem.
IMO there is no such thing as unintended ADL during a call to boost::begin(). you always want it.
By "unintended ADL" I mean what happens when the author of the begin() function that ends up getting called never intended it to be found via ADL for that particular argument type. I suppose I should have written "unintended argument-dependent matching" or something. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:usm2379fu.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > "David Abrahams" <dave@boost-consulting.com> wrote in message | > news:u1x9nzw3b.fsf@boost-consulting.com... | > | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > just consider that all of the begin()'s may have an unconstrained | > primary template version. all three is going to match. | | How likely is that? It doesn't seem bery likely to me. foo::begin | will almost certainly be more specific. who knows. | I don't think you mean "primary template," do you? You're not talking | about using function template specialization are you? I just meant they all have a default version (the primary template) like template <class T > some_thing begin( T& r ); | > | > 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 | > | > you mean by namespaces? | | Yes. then consider a TU where somebody writes using namespace boost; using namespace std; using namespace foo; | > | to prevent unintended ADL, I think it's even less of a problem. | > | > IMO there is no such thing as unintended ADL during a call to | > boost::begin(). you always want it. | | By "unintended ADL" I mean what happens when the author of the begin() | function that ends up getting called never intended it to be found via | ADL for that particular argument type. I suppose I should have | written "unintended argument-dependent matching" or something. hm...I simply can't imagine somebody wanting that ADL should not kick in. If only the language had built-in capabilities for to enable both ADL and qualified syntax... -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:usm2379fu.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > "David Abrahams" <dave@boost-consulting.com> wrote in message | > news:u1x9nzw3b.fsf@boost-consulting.com... | > | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
| > just consider that all of the begin()'s may have an unconstrained | > primary template version. all three is going to match. | | How likely is that? It doesn't seem bery likely to me. foo::begin | will almost certainly be more specific.
who knows.
Well, we're doing this design completely based on speculation, so you have to make some educated guesses in order to proceed.
| I don't think you mean "primary template," do you? You're not talking | about using function template specialization are you?
I just meant they all have a default version (the primary template) like
template <class T > some_thing begin( T& r );
That's a misuse of the term "primary template," which has a specific technical meaning. Why not just say "fully general overload?"
| > | > 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 | > | > you mean by namespaces? | | Yes.
then consider a TU where somebody writes
using namespace boost; using namespace std; using namespace foo;
What about it? ADL doesn't look through using-directives. Furthermore, using-directives are (almost officially) discouraged except for migrating old code.
| > | to prevent unintended ADL, I think it's even less of a problem. | > | > IMO there is no such thing as unintended ADL during a call to | > boost::begin(). you always want it. | | By "unintended ADL" I mean what happens when the author of the begin() | function that ends up getting called never intended it to be found via | ADL for that particular argument type. I suppose I should have | written "unintended argument-dependent matching" or something.
hm...I simply can't imagine somebody wanting that ADL should not kick in.
I don't see how you can say that and also worry about the "ADL lookup problem." It has to be one or the other.
If only the language had built-in capabilities for to enable both ADL and qualified syntax...
What would the point of qualification be if the actual function found might be in some other namespace? -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u8y3u37j0.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > "David Abrahams" <dave@boost-consulting.com> wrote in message | > news:usm2379fu.fsf@boost-consulting.com... | > | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > | I don't think you mean "primary template," do you? You're not talking | > | about using function template specialization are you? | > | > I just meant they all have a default version (the primary template) | > like | > | > template <class T > | > some_thing begin( T& r ); | | That's a misuse of the term "primary template," which has a specific | technical meaning. Why not just say "fully general overload?" I'm using the meaning defined in "C++ Templates" p. 100. | > | > | to prevent unintended ADL, I think it's even less of a problem. | > | > | > | > IMO there is no such thing as unintended ADL during a call to | > | > boost::begin(). you always want it. | > | | > | By "unintended ADL" I mean what happens when the author of the begin() | > | function that ends up getting called never intended it to be found via | > | ADL for that particular argument type. I suppose I should have | > | written "unintended argument-dependent matching" or something. | > | > hm...I simply can't imagine somebody wanting that ADL should not | > kick in. | | I don't see how you can say that and also worry about the "ADL lookup | problem." It has to be one or the other. maybe the concern is not needed. not changing anything is certainly easier for me -Thorsten.

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u8y3u37j0.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > "David Abrahams" <dave@boost-consulting.com> wrote in message | > news:usm2379fu.fsf@boost-consulting.com... | > | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
| > | I don't think you mean "primary template," do you? You're not talking | > | about using function template specialization are you? | > | > I just meant they all have a default version (the primary template) | > like | > | > template <class T > | > some_thing begin( T& r ); | | That's a misuse of the term "primary template," which has a specific | technical meaning. Why not just say "fully general overload?"
I'm using the meaning defined in "C++ Templates" p. 100.
This is also a "primary template:" template <class T, int N> T* begin( T(&)[N] ); If you understand that, then I was wrong to say you're misusing the term, and I just don't understand what distinction you were trying to draw in using it.
| > | > | to prevent unintended ADL, I think it's even less of a problem. | > | > | > | > IMO there is no such thing as unintended ADL during a call to | > | > boost::begin(). you always want it. | > | | > | By "unintended ADL" I mean what happens when the author of the begin() | > | function that ends up getting called never intended it to be found via | > | ADL for that particular argument type. I suppose I should have | > | written "unintended argument-dependent matching" or something. | > | > hm...I simply can't imagine somebody wanting that ADL should not | > kick in. | | I don't see how you can say that and also worry about the "ADL lookup | problem." It has to be one or the other.
maybe the concern is not needed. not changing anything is certainly easier for me
Well, I just don't know. I think we need more experience to be sure. -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (3)
-
David Abrahams
-
Thomas Witt
-
Thorsten Ottosen