Topic: Issue with Pre-Redmond Mailing
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Sat, 25 Sep 2004 19:15:54 GMT Raw View
David Abrahams wrote in news:uacvgzmjx.fsf@boost-consulting.com in
comp.std.c++:
> rtw@freenet.co.uk (Rob Williscroft) writes:
>
>> David Abrahams wrote in news:uy8j2ma7s.fsf@boost-consulting.com in
>> comp.std.c++:
>>
>>> rtw@freenet.co.uk (Rob Williscroft) writes:
>>
>> I'd be much closer to +0 on this if you were trying to change the
>> (complete) rules, It's the two sets of rules coexisting that I'm
>> most against.
>
> I don't like it either. I'm sure we'll discuss it both ways.
>
>>> A laudable goal that I approve of; I just don't approve of the lack
>>> of mechanism ;-). Your approach is "no mechanism: tell library
>>> authors and users to fix their code."
>>
>> Well I belive its "tell the library authors" only.
>
> Well, you're wrong about that, as I believe I've demonstrated. But
> don't worry I'll demonstrate again in a bit. If library authors do a
> perfect job but they still create functions that are designed to be
> found via ADL (i.e. in the same namespace as their types) users will
> still need to be extra careful.
>
>>> Actually, I'm all for that, but I want to provide a better and more
>>> natural mechanism for writing code that's correct in the first
>>> place.
>>>
>>> The problems are ultimately inherent in ADL and namespaces as they
>>> are now specified, and no amount of fixing code will fix the
>>> problem. The problem is that it requires too much syntax and too
>>> much thought to do the right thing.
>>
>> I don't agree, we simply havent learnt the simple rules for writing
>> C++ code with namespaces.
>>
>> 1 ) defenition namespaces: for related and coupled thing's.
>> 2 ) Accessor namespaces: for other defenition namespaces and
>> using declaration's.
>
> I know the rules. They may be "simple" but they add complexity
> syntactic weight and bookkeeping (I won't go into detail unless you
> really can't see that).
Its not a matter of not seeing it, but a matter of not see it as
unexceptable.
> Many _many_ people are reluctant to use
> namespaces at all; getting them to go this far is going to be hard. I
> claim these people are justified in their expectation that "it ought
> to be easier to do the right thing." Other languages have a much more
> straightforward name lookup model, and before ADL C++ did, too.
>
Well maybe, but ADL and namespaces aren't the only C++ feature, that
makes the language non-strightforward, specialization confuses most
people to start with, then they get there head around it and start
being confused about the lack of partial specialization for function
and member templates.
>>>>> Yes, as a library implementor you can prevent this code from
>>>>> looking up the wrong copy function by paying a lot of attention
>>>>> and keeping unrelated functions and data types in separate
>>>>> sub-namespaces so you *could* look it as "not a core problem".
>>>>
>>>> I do, how is *not* defining a complety generic function like
>>>> std::copy in the same namespace as completely unrelated type's
>>>> "paying a lot of attention" ?
>>>
>>> Well, they're clearly not "completely unrelated" or we'd have no
>>> problem. There's a good reason the standard library is all
>>> accessible through the same namespace.
>>
>> Yes, but accessability doesn't require that everything accesable via
>> std:: is defined there.
>
> You don't have to explain that to me.
Its a counter argument, I'm not suggesting you don't understand such
things, I'm quite aware that you do.
> I know what it takes to "do
> the right thing" in the presence of ADL and provide the illusion of a
> single namespace.
>
>>>> Its no harder than not giving std::string a member for opening
>>>> files or for adding complex numbers.
>>>
>>> Every time you have to consider dividing up namespaces it imposes a
>>> mental burden.
>>
>> After the fact, If you divide first, then joining were reasonable
>> and advantagous is easy.
>
> No, dividing first has a mental cost too. It introduces layers,
> names, and groupings that wouldn't otherwise be neccessary.
Of course it has a cost, but it isn't unreasonable, this issue is
similar to writing on big function v writing meny (sub) function's
and the writing one small function that call's the (sub) function's.
>
>>> And then if you're bringing functions into type
>>> namespaces with using-declarations you still need to pay attention
>>> and qualify them.
>>>
>>> Why should functions impose this burden? You don't have to separate
>>> types from one another (except as dictated by functions intended to
>>> be invoked via ADL).
>>
>> They are different things, so different behaviours isn't
>> unreasonable.
>>
>> Unqualified calls are ADL calls, i.e. what happens when you make an
>> unqualified call is an association of function name and the argument
>> types, the problem is that this isn't what we currently expect, but
>
> This "what we currently expect" is a bit patronizing. I know what to
> expect, really, or I wouldn't be making this proposal.
>
>> there is no *fundemental* reason it shouldn't be.
>
> No of course not. There's also no *fundemental* reason not to
> program in plain 'C' or assembly language. But programming in C++
> should be easier than that. If you're going to argue on the basis of
> what's inherent in programming we should stop right here,
No I'm not and I didn't, I'm talking about C++ and how it works (or
is supposed to work) today.
> because all
> I'm interested in is ease-of-use (including
> ease-of-doing-the-right-thing) and expressivity.
>
>>>>> The point of the paper is that calling this a problem in the
>>>>> design and implementation of std:: is asking more of library
>>>>> implementors (at large) than the language should. In other words,
>>>>> "consideration of the effects of ADL" is much too often
>>>>> neccessary.
>>>>
>>>> Narrower scopes (sub-namespaces) alleviate this problem.
>>>
>>> Yes, and users have the same problem.
>>
>> Only when they use libraries implemented without regard to ADL.
>
> No. Let me demonstrate:
>
> namespace lib
> {
> namespace algorithms // Do the right thing
> {
> template <class T>
> T sqrt(T);
>
> template <class T>
> T norm(T x, unsigned kind)
> {
> return kind == 0 ? x < 0 ? -x : x
> : kind == 1 ? sqrt(x * x)
> : 0; // maybe we'd have more cases
> }
>
> template <class T>
> T munge(T x)
> {
> return norm(x, 0); // intentionally find norm through
> ADL
> }
> }
> namespace some_type_ // Do the right thing
> {
> class some_type {};
> void f(some_type, int); // intended to be found via ADL
> }
> using some_type_::some_type; // Make it convenient
> using some_type_::f;
> using algorithms::munge;
> }
>
> namespace user
> {
> class foo;
> void f(lib::some_type, foo*);
>
> void g()
> { // problem #1
> f(lib::some_type(), 0); // silently calls lib::f
This is a problem with how overloading works and the conversion of
0 to void *, it exists independently of namespaces and ADL.
> }
>
> struct rational
> {
> rational(int);
> bool operator<(rational) const;
> rational operator-() const;
> rational operator*(rational) const;
> // ...
> };
>
> int norm(rational, foo*); // unrelated function
>
> void h(rational x)
> { // problem #2
> lib::munge(x); // munge silently calls user::norm
Same problem as above. You can also write a namespace and ADL free
version of the above that exhibits the same problem.
.. Pause to reread your proposal ...
I don't see how your proposal helps here anyway ? I.e. how do I use
explicit namespaces to eliminate or reduce this problem.
> }
> }
>
> I'm sure that if you think about it a bit you can find lots of other
> cases like these.
>
>>>>> As a library implementor, I can tell you that
>>>>> paying attention to these effects is a drag on my ability to write
>>>>> good code. C++ is quite complicated enough, thank you.
>>>>
>>>> Yes it is, but you actually want to make it more complicated:
>>>>
>>>> some_type a, b, c;
>>>> copy( a, b, c );
>>>>
>>>> Currently I see the above code and know (as copy is unqualified
>>>> and unparenthesized) that the call is subject to ADL.
>>>>
>>>> You want me to have to scan back in the TU and check wether the
>>>> namespace is explicit or not and then if it is, I then have to
>>>> scan for unqualified using declaration's, just to make sure.
>>>
>>> 1. Keeping track of which namespaces are explicit is very easy,
>>> unless you have a whole mess of them. But this proposal is
>>> designed to limit namespace proliferation. "Flat is better than
>>> nested" (zen of python).
>>
>> Yes but python is also a modular language, i.e. A flat design can
>> be implemented in a modular (heirarchical) fasion, we can do the
>> same in C++ with nested namespaces and using declarations.
>
> You're missing my point. What you would normally implement in a
> single module in Python may have to be implemented with multiple
> namespaces and using declarations. It's better to be able to flatten
> those out and eliminate the complexity of using declarations.
>
>> Give the "detail" namespcae a unique (within its scope) name and
>> hoist the public interface out of it with using declaration's.
>>
>>>
>>> 2. Unqualified using declarations should be used sparingly at
>>> namespace scope, if at all. In either case, at least ADL doesn't
>>> happen by accident.
>>
>> It *never* happens by accident
>
> I have personally experienced it happening by accident!
>
>> , it happens by design. If the design
>> is an accident
>
> Please. Now you're just playing word games. "By design" normally
> means "not accidentally." You can't have it be "by design" when the
> design is an accident.
Two statments not one:
It is by design, the way the language is designed to work.
std::copy being found when a call of copy( std::vector< > ... ) is made
is an accident caused by the Standard library being designed for pre
ADL C++ and not being updated.
>
>> then either the language (*) or the design of the namespace causing
>> the accident is broken.
>>
>> *) i.e. if ADL is wrong then it should be fixed (I'm +0 that it is
>> wrong).
>
> Wrong? Well, there's no absolute here. It's harder and more
> error-prone than it should be. IMO it's in the category of things
> that should be cleaned up for C++0x.
>
>>> Understanding the meaning of any given call, even if qualified, is
>>> already impossible to do with only local information. There could
>>> be multiple overloads, and there could be specializations (or
>>> dispatching through class template partial specializations). My
>>> proposal makes that problem marginally worse in exchange for a huge
>>> reduction in error-prone-ness.
>>
>> If I need to know in that level of detail what a function call
>> does then qualification is not unreasonable IMO.
>
> You're missing my point.
No I'm dissagreeing.
> Qualification doesn't help very much in
> reality.
For an N argument function it potentialy removes N overload set's
found by ADL, plus overload set's from parent namespaces.
>
>>>> Also isn't dealing with these kind of details one of the
>>>> reason's libraries exist, the library author does it so the
>>>> end user doesn't have too.
>>>
>>> The user has the same problems the library author has. Any careless
>>> unqualified call might pick up a library function. Even if
>>> libraries are all subdivided as you propose, it can pick up one of
>>> the functions intended for ADL.
>>
>> As it should IMO, but then I like ADL (I may be the only one :).
>
> First you claimed that users can't get in trouble by not separating
> functions and classes when the libraries are written properly. Now it
> sounds like you're saying the poor users deserve whatever they get.
No that isn't what I said, overload resolution picks the most appropriate
overload, ADL enhances that (IMO).
>
>>>> Your're proposal (kind of) implies: No library authors should
>>>> just write blob namespace libraries and the language and the
>>>> *user* should deal with it.
>>>
>>> ?? My proposal would make it possible for the user to worry much
>>> less about these things.
>>
>> Do users (*) worry about such thing's now ?
>
> If they want to do it right they do.
>
>> *) users != library implementors using other libraries.
>
> Creating an arbitrarily higher standard for library implementors and
> users is also bad for the future of the language.
The language should be usable by people of all levels of experience,
but it isn't unreasonable to expect those that write code for use
by others to have "above average" expertise.
Thats part of what libraries are all about, encapsulating expertise.
>
>>>> I don't mind the language dealing with it, I do object to the
>>>> user having too.
>>>
>>> I haven't a clue what you're referring to.
>>
>> The complexity for users increases with this proposal, more
>> expertise not less (or the same) is required of them.
>
> It depends. When we get to the point where all namespaces are
> explicit, it'll be simpler.
Ok, that is something new:
#include "myint.hpp"
explicit namespace app
{
mylib::myint f()
{
#include "myint_explicit_using.hpp"
mylib::myint i = 1, j = 2;
return i + j;
}
}
You suggested to Walter Bright that a compulter language should
have core features that enable libraries that do what you could
do with core types and syntax, but here you want to remove what
we already have!
explicit namespace generic
{
template < typename T > T add( T const &lhs, T const &rhs )
{
using operator +;
return lhs + rhs;
}
}
+10 on the synatic noise scale!
>
[snip something we actualy agreed on ;)]
>>
>> I see your POV, but I would see this change as handy feature I would
>> occasionaly use, you (I suspect) see this as somthing you would need
>> to use all the time, hence a noisy feature.
>
> Yep. Not just syntactically but mentally. I want to take ADL *out*
> of the sequence of mental gymnastics required of someone writing code
> unless explicitly requested.
There is lots of "mental gymnastics" required in writing C++, I don't
consider ADL to be especialy hard.
> Also I consider the fact that
> qualification or parentheses are needed to reliably call a function in
> the same namespace without other overloads being found by ADL to be
> perverse.
I consider wanting to do this to be the excpetion, you seem to consider
it the rule.
Why are overloads from parent namespaces fine and overloads from ADL
namespaces problematic ?
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: David Abrahams <dave@boost-consulting.com>
Date: Mon, 27 Sep 2004 00:32:42 GMT Raw View
rtw@freenet.co.uk (Rob Williscroft) writes:
>>> Unqualified calls are ADL calls, i.e. what happens when you make an
>>> unqualified call is an association of function name and the argument
>>> types, the problem is that this isn't what we currently expect, but
>>
>> This "what we currently expect" is a bit patronizing. I know what to
>> expect, really, or I wouldn't be making this proposal.
>>
>>> there is no *fundemental* reason it shouldn't be.
>>
>> No of course not. There's also no *fundemental* reason not to
>> program in plain 'C' or assembly language. But programming in C++
>> should be easier than that. If you're going to argue on the basis of
>> what's inherent in programming we should stop right here,
>
> No I'm not and I didn't, I'm talking about C++ and how it works (or
> is supposed to work) today.
Excuse me; did I misinterpret your argument about whether the reasons
for design choices are fundamental?
>> because all I'm interested in is ease-of-use (including
>> ease-of-doing-the-right-thing) and expressivity.
>>
>>>>>> The point of the paper is that calling this a problem in the
>>>>>> design and implementation of std:: is asking more of library
>>>>>> implementors (at large) than the language should. In other words,
>>>>>> "consideration of the effects of ADL" is much too often
>>>>>> neccessary.
>>>>>
>>>>> Narrower scopes (sub-namespaces) alleviate this problem.
>>>>
>>>> Yes, and users have the same problem.
>>>
>>> Only when they use libraries implemented without regard to ADL.
>>
>> No. Let me demonstrate:
>>
>> namespace lib
>> {
>> namespace algorithms // Do the right thing
>> {
>> template <class T>
>> T sqrt(T);
>>
>> template <class T>
>> T norm(T x, unsigned kind)
>> {
>> return kind == 0 ? x < 0 ? -x : x
>> : kind == 1 ? sqrt(x * x)
>> : 0; // maybe we'd have more cases
>> }
>>
>> template <class T>
>> T munge(T x)
>> {
>> return norm(x, 0); // intentionally find norm through
>> ADL
>> }
>> }
>> namespace some_type_ // Do the right thing
>> {
>> class some_type {};
>> void f(some_type, int); // intended to be found via ADL
>> }
>> using some_type_::some_type; // Make it convenient
>> using some_type_::f;
>> using algorithms::munge;
>> }
>>
>> namespace user
>> {
>> class foo;
>> void f(lib::some_type, foo*);
>>
>> void g()
>> { // problem #1
>> f(lib::some_type(), 0); // silently calls lib::f
>
> This is a problem with how overloading works and the conversion of
> 0 to void *, it exists independently of namespaces and ADL.
There are lots of other examples. You can construct the same kinds of
issues with base and derived classes and other implicit conversions.
If you control your own namespace and your parent namespaces, it
doesn't happen, except via ADL.
>> }
>>
>> struct rational
>> {
>> rational(int);
>> bool operator<(rational) const;
>> rational operator-() const;
>> rational operator*(rational) const;
>> // ...
>> };
>>
>> int norm(rational, foo*); // unrelated function
>>
>> void h(rational x)
>> { // problem #2
>> lib::munge(x); // munge silently calls user::norm
>
> Same problem as above. You can also write a namespace and ADL free
> version of the above that exhibits the same problem.
It depends on whether you think it's the same problem. Remember, I'm
not proposing to get rid of namespaces. I'm proposing to make them
the intuitively insulated scopes that they should be.
> .. Pause to reread your proposal ...
>
> I don't see how your proposal helps here anyway ? I.e. how do I use
> explicit namespaces to eliminate or reduce this problem.
Just make all the namespaces explicit. Then if you control the
contents of your namespace and your parents', you don't get "spooky
action at a distance."
>> }
>> }
>>
>> I'm sure that if you think about it a bit you can find lots of other
>> cases like these.
>>>> 1. Keeping track of which namespaces are explicit is very easy,
>>>> unless you have a whole mess of them. But this proposal is
>>>> designed to limit namespace proliferation. "Flat is better than
>>>> nested" (zen of python).
>>>
>>> Yes but python is also a modular language, i.e. A flat design can
>>> be implemented in a modular (heirarchical) fasion, we can do the
>>> same in C++ with nested namespaces and using declarations.
>>
>> You're missing my point. What you would normally implement in a
>> single module in Python may have to be implemented with multiple
>> namespaces and using declarations. It's better to be able to flatten
>> those out and eliminate the complexity of using declarations.
>>
>>> Give the "detail" namespcae a unique (within its scope) name and
>>> hoist the public interface out of it with using declaration's.
>>>
>>>>
>>>> 2. Unqualified using declarations should be used sparingly at
>>>> namespace scope, if at all. In either case, at least ADL doesn't
>>>> happen by accident.
>>>
>>> It *never* happens by accident
>>
>> I have personally experienced it happening by accident!
>>
>>> , it happens by design. If the design
>>> is an accident
>>
>> Please. Now you're just playing word games. "By design" normally
>> means "not accidentally." You can't have it be "by design" when the
>> design is an accident.
>
> Two statments not one:
>
> It is by design, the way the language is designed to work.
>
> std::copy being found when a call of copy( std::vector< > ... ) is made
> is an accident caused by the Standard library being designed for pre
> ADL C++ and not being updated.
Please. You just contradicted my suggestion that ADL can happen by
accident. I have experienced accidental ADL on several occasions.
Neither the author of the caller nor that of the callee expected ADL
to take effect in that situation. We really can't argue about that
statement because it is a fact that I witnessed firsthand.
>>>> Understanding the meaning of any given call, even if qualified, is
>>>> already impossible to do with only local information. There could
>>>> be multiple overloads, and there could be specializations (or
>>>> dispatching through class template partial specializations). My
>>>> proposal makes that problem marginally worse in exchange for a huge
>>>> reduction in error-prone-ness.
>>>
>>> If I need to know in that level of detail what a function call
>>> does then qualification is not unreasonable IMO.
>>
>> You're missing my point.
>
> No I'm dissagreeing.
>> Qualification doesn't help very much in reality.
>
> For an N argument function it potentialy removes N overload set's
> found by ADL, plus overload set's from parent namespaces.
Which is exactly the same set of possibilities eliminated within an
explicit namespace. Qualification doesn't help very much with how far
and where you have to search. Consider that function templates can be
specialized. Consider that overloads can come from any number of
headers. Either way, if you really want to be sure of which code gets
called, you have to preprocess the TU and do an exhaustive search or
trace it in a debugger.
>>>>> Also isn't dealing with these kind of details one of the
>>>>> reason's libraries exist, the library author does it so the
>>>>> end user doesn't have too.
>>>>
>>>> The user has the same problems the library author has. Any careless
>>>> unqualified call might pick up a library function. Even if
>>>> libraries are all subdivided as you propose, it can pick up one of
>>>> the functions intended for ADL.
>>>
>>> As it should IMO, but then I like ADL (I may be the only one :).
>>
>> First you claimed that users can't get in trouble by not separating
>> functions and classes when the libraries are written properly. Now it
>> sounds like you're saying the poor users deserve whatever they get.
>
> No that isn't what I said, overload resolution picks the most appropriate
> overload, ADL enhances that (IMO).
Except when it doesn't. Those cases tend to be rare, but they're very
hard to check for, and coding to prevent them takes a great deal of
attention.
>> It depends. When we get to the point where all namespaces are
>> explicit, it'll be simpler.
>
> Ok, that is something new:
>
> #include "myint.hpp"
> explicit namespace app
> {
> mylib::myint f()
> {
> #include "myint_explicit_using.hpp"
> mylib::myint i = 1, j = 2;
> return i + j;
> }
> }
>
> You suggested to Walter Bright that a compulter language should
> have core features that enable libraries that do what you could
> do with core types and syntax, but here you want to remove what
> we already have!
What's being removed?
> explicit namespace generic
> {
> template < typename T > T add( T const &lhs, T const &rhs )
> {
> using operator +;
> return lhs + rhs;
> }
> }
>
> +10 on the synatic noise scale!
Oh, really? That using declaration obscures something?
>> Yep. Not just syntactically but mentally. I want to take ADL *out*
>> of the sequence of mental gymnastics required of someone writing code
>> unless explicitly requested.
>
> There is lots of "mental gymnastics" required in writing C++, I don't
> consider ADL to be especialy hard.
It's not hard to understand, it's just easily overlooked.
>> Also I consider the fact that
>> qualification or parentheses are needed to reliably call a function in
>> the same namespace without other overloads being found by ADL to be
>> perverse.
>
> I consider wanting to do this to be the excpetion, you seem to consider
> it the rule.
I consider it quite common. I very often write functions in the same
namespace that call one another. That's called "reuse." Please
don't tell me that every function should be segregated into its own
namespace. That's called "redundant."
> Why are overloads from parent namespaces fine and overloads from ADL
> namespaces problematic ?
Because the overloads from ADL come from namespaces you generally
don't control.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Louis Lavery" <louis@laver.demon.co.uk>
Date: Mon, 27 Sep 2004 16:32:01 GMT Raw View
David Abrahams <dave@boost-consulting.com> wrote in message
news:umzzclgyt.fsf@boost-consulting.com...
> rtw@freenet.co.uk (Rob Williscroft) writes:
>
[snip]
> >> I have personally experienced it happening by accident!
> >>
> >>> , it happens by design. If the design
> >>> is an accident
> >>
> >> Please. Now you're just playing word games. "By design" normally
> >> means "not accidentally." You can't have it be "by design" when the
> >> design is an accident.
> >
> > Two statments not one:
> >
> > It is by design, the way the language is designed to work.
> >
> > std::copy being found when a call of copy( std::vector< > ... ) is
made
> > is an accident caused by the Standard library being designed for pre
> > ADL C++ and not being updated.
>
> Please. You just contradicted my suggestion that ADL can happen by
> accident. I have experienced accidental ADL on several occasions.
> Neither the author of the caller nor that of the callee expected ADL
> to take effect in that situation. We really can't argue about that
> statement because it is a fact that I witnessed firsthand.
Could you please present a simple example of how it can happen by
accident, I'm having a problem seeing how it can.
Thanks,
Louis.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: David Abrahams <dave@boost-consulting.com>
Date: Tue, 28 Sep 2004 01:43:51 GMT Raw View
"Louis Lavery" <louis@laver.demon.co.uk> writes:
> David Abrahams <dave@boost-consulting.com> wrote in message
> news:umzzclgyt.fsf@boost-consulting.com...
>> rtw@freenet.co.uk (Rob Williscroft) writes:
>>
>
> [snip]
>
>> >> I have personally experienced it happening by accident!
>> >>
>> >>> , it happens by design. If the design
>> >>> is an accident
>> >>
>> >> Please. Now you're just playing word games. "By design" normally
>> >> means "not accidentally." You can't have it be "by design" when the
>> >> design is an accident.
>> >
>> > Two statments not one:
>> >
>> > It is by design, the way the language is designed to work.
>> >
>> > std::copy being found when a call of copy( std::vector< > ... ) is
> made
>> > is an accident caused by the Standard library being designed for pre
>> > ADL C++ and not being updated.
>>
>> Please. You just contradicted my suggestion that ADL can happen by
>> accident. I have experienced accidental ADL on several occasions.
>> Neither the author of the caller nor that of the callee expected ADL
>> to take effect in that situation. We really can't argue about that
>> statement because it is a fact that I witnessed firsthand.
>
> Could you please present a simple example of how it can happen by
> accident, I'm having a problem seeing how it can.
Programmer builds a type called "fill", used for detecting non-zero
elements in factorized matrices (ignore the details -- they just
justify the name "fill" a little)
Programmer instantiates lib::vector<fill>.
lib also happens to contain a function called fill. lib::vector calls
this fill function -- without qualification -- as an implementation
detail. Yes, the lib author should have used qualification here, or
placed fill in a separate namespace, but the problem is easy to
overlook.
ADL finds user::fill and pronounces an error when the constructor
arguments don't match. There's nothing programmer can do about this
problem other than renaming his class. The mistake was made by the
lib author, who never intended to use any fill but his own, but the
language provides no support for detecting these mistakes. The
mistake of not qualifying a call to a function in the same namespace
is one of the easiest to make, and results in nice, clean-looking
code. It doesn't stick out like reinterpret_cast<Foo> does.
HTH,
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Rob Williscroft <rtw@freenet.co.uk>
Date: Tue, 28 Sep 2004 14:18:24 GMT Raw View
David Abrahams wrote in news:umzzclgyt.fsf@boost-consulting.com in
comp.std.c++:
>>> No. Let me demonstrate:
>>>
>>> namespace lib
>>> {
>>> namespace algorithms // Do the right thing
>>> {
>>> template <class T>
>>> T sqrt(T);
>>>
>>> template <class T>
>>> T norm(T x, unsigned kind)
>>> {
>>> return kind == 0 ? x < 0 ? -x : x
>>> : kind == 1 ? sqrt(x * x)
>>> : 0; // maybe we'd have more cases
>>> }
>>>
>>> template <class T>
>>> T munge(T x)
>>> {
>>> return norm(x, 0); // intentionally find norm through
>>> ADL
>>> }
>>> }
>>> namespace some_type_ // Do the right thing
>>> {
>>> class some_type {};
>>> void f(some_type, int); // intended to be found via ADL
>>> }
>>> using some_type_::some_type; // Make it convenient
>>> using some_type_::f;
>>> using algorithms::munge;
>>> }
>>>
>>> namespace user
>>> {
>>> class foo;
>>> void f(lib::some_type, foo*);
>>>
>>> void g()
>>> { // problem #1
>>> f(lib::some_type(), 0); // silently calls lib::f
>>
>> This is a problem with how overloading works and the conversion of
>> 0 to void *, it exists independently of namespaces and ADL.
>
> There are lots of other examples. You can construct the same kinds of
> issues with base and derived classes and other implicit conversions.
Greedy conversion's (particularly templates) are alway's going to
be a problem, however in a sutibly designed namespace they can also
be very useful, explicit namespaces will reduce this potential utility.
> If you control your own namespace and your parent namespaces, it
> doesn't happen, except via ADL.
Control of you own and parent namespaces *requires* that you manage
them, i.e. small, fine-grained, providing a limited set of functionality.
IOW what namespace std (currently) isn't.
Control can also be taken with a qualified or perenthesised call, it
requires knowledge of the call site and of the target overload set,
it doesn't require complete control of several namespaces.
>
>>> }
>>>
>>> struct rational
>>> {
>>> rational(int);
>>> bool operator<(rational) const;
>>> rational operator-() const;
>>> rational operator*(rational) const;
>>> // ...
>>> };
>>>
>>> int norm(rational, foo*); // unrelated function
>>>
>>> void h(rational x)
>>> { // problem #2
>>> lib::munge(x); // munge silently calls user::norm
>>
>> Same problem as above. You can also write a namespace and ADL free
>> version of the above that exhibits the same problem.
>
> It depends on whether you think it's the same problem. Remember, I'm
> not proposing to get rid of namespaces. I'm proposing to make them
> the intuitively insulated scopes that they should be.
"intuitive" ?:
#include <iostream>
#include <ostream>
#include <complex>
explicit namespace user
{
template < typename T >
T operator + ( T a, T b )
{
using operator <<;
std::cout << a << " + " << b << '\n';
using operator +;
return a + b;
}
template < typename T >
T f( T a, T b )
{
return a + b;
}
}
int main()
{
user::f( 1, 2 );
user::f(
std::complex< double >( 1, 2 ),
std::complex< double >( 3, 4 )
);
}
The first call doesn't print anything (AFAICT), the second does.
though I did have to check the standard to make sure.
>
>> .. Pause to reread your proposal ...
>>
>> I don't see how your proposal helps here anyway ? I.e. how do I use
>> explicit namespaces to eliminate or reduce this problem.
>
> Just make all the namespaces explicit. Then if you control the
> contents of your namespace and your parents', you don't get "spooky
> action at a distance."
How so: lib::algorithms::munge is *designed* to call a function
norm( lvalue_T, 0 )
via ADL, it will still find
user::norm( rational, foo * );
There will still be one and only one way to prevent a "greedy" function
being associated via ADL with types it isn't really assosiated with and
thats by defining it in a namespace that *only* defines the types it is
associated with.
>
>>> }
>>> }
>>>
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Wed, 22 Sep 2004 18:01:01 GMT Raw View
rtw@freenet.co.uk (Rob Williscroft) writes:
> Either way I don't want more complicated lookup rules,
> particularly two sets of them.
My proposal doesn't introduce complicated lookup rules. The lookup
procedure in an explicit namespace is just a simplification of
existing rules.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Wed, 22 Sep 2004 19:40:44 GMT Raw View
Ben Hutchings wrote in news:slrncl0ha8.pk.ben-public-
nospam@decadentplace.org.uk in comp.std.c++:
>
> That just makes "swap" effectively a reserved name in all class scopes
> rather than in all namespace scopes. How is that an improvement?
>
>
Well it depends on what has_swap_member detects, at the very minimum
I would expect it to detect a member *signature* void swap( T & ),
so that is all that would be reserved. Additionally if somebody
wanted to have such a member and have std::swap still do its thing,
they could specialize have_swap_member.
But as Howard has already pointed out this is no use for current
and future C++ as it silently breaks valid code.
Still it would be nice to have some mechanism where swap could
be provided at just one place, rather than two.
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Wed, 22 Sep 2004 19:40:46 GMT Raw View
David Abrahams wrote in news:u4qlqnq3m.fsf@boost-consulting.com in
comp.std.c++:
>> Either way I don't want more complicated lookup rules,
>> particularly two sets of them.
>
> My proposal doesn't introduce complicated lookup rules. The lookup
> procedure in an explicit namespace is just a simplification of
> existing rules.
>
Which makes the lookup rules more complicated:
new_complexity =
current_complexity
+ complexity_of_is_this_an_explicit_namespace
+ complexity_of_your_new_rules
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 23 Sep 2004 16:09:38 GMT Raw View
rtw@freenet.co.uk (Rob Williscroft) writes:
> David Abrahams wrote in news:u1xgw38mq.fsf@boost-consulting.com in
> comp.std.c++:
>
>>> The problem above *isn't* a core language problem, its that std::copy
>>> (and indeed the whole std namespace) was designed and implemented
>>> (quite understandably IMO) without any consideration of the effects
>>> of ADL.
>>
>> You seem to have completely missed the point of the paper.
>
> Well maybe so, but that doesn't matter, I didn't miss: "a different
> kind of namespace with new lookup rules". What you're proposing to
> change is more important than why you want to change it.
I'm not proposing to change anything, unfortunately. I'd rather do
that, but for backward compatibility we are stuck with the
possibility of C++98 namespaces.
> FWIW I belive the point (of the explicit namespace part at least) is
> to enable libraries to be writen as they are by many people now but
> without ADL problem's
That's not all. It also permits user code to be written as it is now
by many people without ADL problems. It's also aimed at making the
use of ADL more explicit than it is now. It's also aimed at reducing
the amount of syntactic noise involved in writing ADL-safe code.
> a laudable goal I approve of I just don't approve of the
> mechanism. I'd much rather other libraries didn't cause the
> problem's in the first place.
A laudable goal that I approve of; I just don't approve of the lack of
mechanism ;-). Your approach is "no mechanism: tell library authors
and users to fix their code." Actually, I'm all for that, but I want
to provide a better and more natural mechanism for writing code that's
correct in the first place.
The problems are ultimately inherent in ADL and namespaces as they are
now specified, and no amount of fixing code will fix the problem. The
problem is that it requires too much syntax and too much thought to do
the right thing.
>> Yes, as a library implementor you can prevent this code from
>> looking up the wrong copy function by paying a lot of attention and
>> keeping unrelated functions and data types in separate
>> sub-namespaces so you *could* look it as "not a core problem".
>
> I do, how is *not* defining a complety generic function like std::copy
> in the same namespace as completely unrelated type's "paying a lot of
> attention" ?
Well, they're clearly not "completely unrelated" or we'd have no
problem. There's a good reason the standard library is all accessible
through the same namespace.
> Its no harder than not giving std::string a member for opening files
> or for adding complex numbers.
Every time you have to consider dividing up namespaces it imposes a
mental burden. And then if you're bringing functions into type
namespaces with using-declarations you still need to pay attention and
qualify them.
Why should functions impose this burden? You don't have to separate
types from one another (except as dictated by functions intended to be
invoked via ADL).
>
>> The point of the paper is that calling this a problem in the design
>> and implementation of std:: is asking more of library implementors
>> (at large) than the language should. In other words,
>> "consideration of the effects of ADL" is much too often neccessary.
>
> Narrower scopes (sub-namespaces) alleviate this problem.
Yes, and users have the same problem.
>> As a library implementor, I can tell you that
>> paying attention to these effects is a drag on my ability to write
>> good code. C++ is quite complicated enough, thank you.
>
> Yes it is, but you actually want to make it more complicated:
>
> some_type a, b, c;
> copy( a, b, c );
>
> Currently I see the above code and know (as copy is unqualified
> and unparenthesized) that the call is subject to ADL.
>
> You want me to have to scan back in the TU and check wether the
> namespace is explicit or not and then if it is, I then have to
> scan for unqualified using declaration's, just to make sure.
1. Keeping track of which namespaces are explicit is very easy,
unless you have a whole mess of them. But this proposal is
designed to limit namespace proliferation. "Flat is better than
nested" (zen of python).
2. Unqualified using declarations should be used sparingly at
namespace scope, if at all. In either case, at least ADL doesn't
happen by accident.
Understanding the meaning of any given call, even if qualified, is
already impossible to do with only local information. There could be
multiple overloads, and there could be specializations (or dispatching
through class template partial specializations). My proposal makes
that problem marginally worse in exchange for a huge reduction in
error-prone-ness.
> Also isn't dealing with these kind of details one of the
> reason's libraries exist, the library author does it so the
> end user doesn't have too.
The user has the same problems the library author has. Any careless
unqualified call might pick up a library function. Even if libraries
are all subdivided as you propose, it can pick up one of the
functions intended for ADL.
> Your're proposal (kind of) implies: No library authors should
> just write blob namespace libraries and the language and the
> *user* should deal with it.
?? My proposal would make it possible for the user to worry much
less about these things.
> I don't mind the language dealing with it, I do object to the
> user having too.
I haven't a clue what you're referring to.
>> It is a fact that if you intend to call a function in your own
>> namespace, you'd better use a qualified call.
>
> Yes, a unique function needs a unique name, its unfortunate that
> std::copy doesn't
doesn't what? need a unique name? (??)
::std::copy certainly is a unique name, so I don't see what you're
getting at.
> as its associated with types with which it has no relation.
>
>> Unless the code is
>> going to be frozen for all time and the argument types will never
>> change in ways you didn't anticipate, you have to do it to prevent
>> unintended consequences down the road when the code is maintained.
>>
>
> And if you do that, you do it at one place, the call site, with
> qualification or parentheses, maintainers don't have to analyze
> the whole TU inorder to see what is going on.
They still do. But are you suggesting that requiring that level of
explicitness is a good thing? You don't demand it for types, do
you? When referring to types in the same namespace you don't qualify
them, do you?
> Still its a cure not pervention.
>
> If I had a time machine I'd go back and suggest that ADL be
> explicitly enabled (maybe overload the meaning of friend or
> operator), then std::copy et al would be what they were
> intended to be in the first place, function's that are called
> fully qualified or when there names have been hoisted into scope.
>
> But its unlikely I'll ever get that, so how about:
>
> namespace std
> {
> template < ... >
> explicit ... copy( ... );
> }
>
> It worked for (i.e. disabled) unintended converting ctor's.
I assume you want the addition of "explicit" to change the way copy
is looked up here?
Well, it's not a bad idea, but it doesn't solve the same problems
unless everyone does it (users too). New lookup rules within an
explicit namespace prevent *any* copy(...) from being unintentionally
found via ADL. Ultimately your suggestion adds too much syntactic
noise in my opinion.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Thu, 23 Sep 2004 19:26:37 GMT Raw View
David Abrahams wrote in news:uy8j2ma7s.fsf@boost-consulting.com in
comp.std.c++:
> rtw@freenet.co.uk (Rob Williscroft) writes:
>
>>
>> Well maybe so, but that doesn't matter, I didn't miss: "a different
>> kind of namespace with new lookup rules". What you're proposing to
>> change is more important than why you want to change it.
>
> I'm not proposing to change anything, unfortunately. I'd rather do
> that, but for backward compatibility we are stuck with the
> possibility of C++98 namespaces.
I'd be much closer to +0 on this if you were trying to change the
(complete) rules, It's the two sets of rules coexisting that I'm
most against.
>
>> FWIW I belive the point (of the explicit namespace part at least) is
>> to enable libraries to be writen as they are by many people now but
>> without ADL problem's
>
> That's not all. It also permits user code to be written as it is now
> by many people without ADL problems. It's also aimed at making the
> use of ADL more explicit than it is now. It's also aimed at reducing
> the amount of syntactic noise involved in writing ADL-safe code.
>
>> a laudable goal I approve of I just don't approve of the
>> mechanism. I'd much rather other libraries didn't cause the
>> problem's in the first place.
>
> A laudable goal that I approve of; I just don't approve of the lack of
> mechanism ;-). Your approach is "no mechanism: tell library authors
> and users to fix their code."
Well I belive its "tell the library authors" only.
> Actually, I'm all for that, but I want
> to provide a better and more natural mechanism for writing code that's
> correct in the first place.
>
> The problems are ultimately inherent in ADL and namespaces as they are
> now specified, and no amount of fixing code will fix the problem. The
> problem is that it requires too much syntax and too much thought to do
> the right thing.
I don't agree, we simply havent learnt the simple rules for writing
C++ code with namespaces.
1 ) defenition namespaces: for related and coupled thing's.
2 ) Accessor namespaces: for other defenition namespaces and
using declaration's.
>
>>> Yes, as a library implementor you can prevent this code from
>>> looking up the wrong copy function by paying a lot of attention and
>>> keeping unrelated functions and data types in separate
>>> sub-namespaces so you *could* look it as "not a core problem".
>>
>> I do, how is *not* defining a complety generic function like std::copy
>> in the same namespace as completely unrelated type's "paying a lot of
>> attention" ?
>
> Well, they're clearly not "completely unrelated" or we'd have no
> problem. There's a good reason the standard library is all accessible
> through the same namespace.
Yes, but accessability doesn't require that everything accesable via
std:: is defined there.
>
>> Its no harder than not giving std::string a member for opening files
>> or for adding complex numbers.
>
> Every time you have to consider dividing up namespaces it imposes a
> mental burden.
After the fact, If you divide first, then joining were reasonable
and advantagous is easy.
> And then if you're bringing functions into type
> namespaces with using-declarations you still need to pay attention and
> qualify them.
>
> Why should functions impose this burden? You don't have to separate
> types from one another (except as dictated by functions intended to be
> invoked via ADL).
They are different things, so different behaviours isn't unreasonable.
Unqualified calls are ADL calls, i.e. what happens when you make an
unqualified call is an association of function name and the argument
types, the problem is that this isn't what we currently expect, but
there is no *fundemental* reason it shouldn't be.
>>
>>> The point of the paper is that calling this a problem in the design
>>> and implementation of std:: is asking more of library implementors
>>> (at large) than the language should. In other words,
>>> "consideration of the effects of ADL" is much too often neccessary.
>>
>> Narrower scopes (sub-namespaces) alleviate this problem.
>
> Yes, and users have the same problem.
Only when they use libraries implemented without regard to ADL.
>
>>> As a library implementor, I can tell you that
>>> paying attention to these effects is a drag on my ability to write
>>> good code. C++ is quite complicated enough, thank you.
>>
>> Yes it is, but you actually want to make it more complicated:
>>
>> some_type a, b, c;
>> copy( a, b, c );
>>
>> Currently I see the above code and know (as copy is unqualified
>> and unparenthesized) that the call is subject to ADL.
>>
>> You want me to have to scan back in the TU and check wether the
>> namespace is explicit or not and then if it is, I then have to
>> scan for unqualified using declaration's, just to make sure.
>
> 1. Keeping track of which namespaces are explicit is very easy,
> unless you have a whole mess of them. But this proposal is
> designed to limit namespace proliferation. "Flat is better than
> nested" (zen of python).
Yes but python is also a modular language, i.e. A flat design can
be implemented in a modular (heirarchical) fasion, we can do the
same in C++ with nested namespaces and using declarations.
Give the "detail" namespcae a unique (within its scope) name and
hoist the public interface out of it with using declaration's.
>
> 2. Unqualified using declarations should be used sparingly at
> namespace scope, if at all. In either case, at least ADL doesn't
> happen by accident.
It *never* happens by accident, it happens by design. If the design
is an accident then either the language (*) or the design of the
namespace causing the accident is broken.
*) i.e. if ADL is wrong then it should be fixed (I'm +0 that it is
wrong).
>
> Understanding the meaning of any given call, even if qualified, is
> already impossible to do with only local information. There could be
> multiple overloads, and there could be specializations (or dispatching
> through class template partial specializations). My proposal makes
> that problem marginally worse in exchange for a huge reduction in
> error-prone-ness.
If I need to know in that level of detail what a function call
does then qualification is not unreasonable IMO.
>
>> Also isn't dealing with these kind of details one of the
>> reason's libraries exist, the library author does it so the
>> end user doesn't have too.
>
> The user has the same problems the library author has. Any careless
> unqualified call might pick up a library function. Even if libraries
> are all subdivided as you propose, it can pick up one of the
> functions intended for ADL.
As it should IMO, but then I like ADL (I may be the only one :).
>
>> Your're proposal (kind of) implies: No library authors should
>> just write blob namespace libraries and the language and the
>> *user* should deal with it.
>
> ?? My proposal would make it possible for the user to worry much
> less about these things.
Do users (*) worry about such thing's now ?
*) users != library implementors using other libraries.
>
>> I don't mind the language dealing with it, I do object to the
>> user having too.
>
> I haven't a clue what you're referring to.
The complexity for users increases with this proposal, more
expertise not less (or the same) is required of them.
>
>>> It is a fact that if you intend to call a function in your own
>>> namespace, you'd better use a qualified call.
>>
>> Yes, a unique function needs a unique name, its unfortunate that
>> std::copy doesn't
>
> doesn't what? need a unique name? (??)
>::std::copy certainly is a unique name, so I don't see what you're
> getting at.
All function's have a fully qualified unique name, some (std::copy
included) are also accesable via ADL using ther short name, std::copy
shouldn't be such a function, it should only be accesable with its
fully qualified name or via a using declaration/statement.
>
>> as its associated with types with which it has no relation.
>>
>>> Unless the code is
>>> going to be frozen for all time and the argument types will never
>>> change in ways you didn't anticipate, you have to do it to prevent
>>> unintended consequences down the road when the code is maintained.
>>>
>>
>> And if you do that, you do it at one place, the call site, with
>> qualification or parentheses, maintainers don't have to analyze
>> the whole TU inorder to see what is going on.
>
> They still do. But are you suggesting that requiring that level of
> explicitness is a good thing? You don't demand it for types, do
> you? When referring to types in the same namespace you don't qualify
> them, do you?
I don't demand it of function call's, but I think in ADL, so maybe
thats just me.
>
>> Still its a cure not pervention.
>>
>> If I had a time machine I'd go back and suggest that ADL be
>> explicitly enabled (maybe overload the meaning of friend or
>> operator), then std::copy et al would be what they were
>> intended to be in the first place, function's that are called
>> fully qualified or when there names have been hoisted into scope.
>>
>> But its unlikely I'll ever get that, so how about:
>>
>> namespace std
>> {
>> template < ... >
>> explicit ... copy( ... );
>> }
>>
>> It worked for (i.e. disabled) unintended converting ctor's.
>
> I assume you want the addition of "explicit" to change the way copy
> is looked up here?
Yep.
>
> Well, it's not a bad idea, but it doesn't solve the same problems
> unless everyone does it (users too). New lookup rules within an
> explicit namespace prevent *any* copy(...) from being unintentionally
> found via ADL. Ultimately your suggestion adds too much syntactic
> noise in my opinion.
>
I see your POV, but I would see this change as handy feature I would
occasionaly use, you (I suspect) see this as somthing you would need
to use all the time, hence a noisy feature.
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: David Abrahams <dave@boost-consulting.com>
Date: Thu, 23 Sep 2004 17:03:13 CST Raw View
rtw@freenet.co.uk (Rob Williscroft) writes:
> David Abrahams wrote in news:uy8j2ma7s.fsf@boost-consulting.com in
> comp.std.c++:
>
>> rtw@freenet.co.uk (Rob Williscroft) writes:
>>
>
>>>
>>> Well maybe so, but that doesn't matter, I didn't miss: "a different
>>> kind of namespace with new lookup rules". What you're proposing to
>>> change is more important than why you want to change it.
>>
>> I'm not proposing to change anything, unfortunately. I'd rather do
>> that, but for backward compatibility we are stuck with the
>> possibility of C++98 namespaces.
>
> I'd be much closer to +0 on this if you were trying to change the
> (complete) rules, It's the two sets of rules coexisting that I'm
> most against.
I don't like it either. I'm sure we'll discuss it both ways.
>>> FWIW I belive the point (of the explicit namespace part at least) is
>>> to enable libraries to be writen as they are by many people now but
>>> without ADL problem's
>>
>> That's not all. It also permits user code to be written as it is now
>> by many people without ADL problems. It's also aimed at making the
>> use of ADL more explicit than it is now. It's also aimed at reducing
>> the amount of syntactic noise involved in writing ADL-safe code.
>>
>>> a laudable goal I approve of I just don't approve of the
>>> mechanism. I'd much rather other libraries didn't cause the
>>> problem's in the first place.
>>
>> A laudable goal that I approve of; I just don't approve of the lack of
>> mechanism ;-). Your approach is "no mechanism: tell library authors
>> and users to fix their code."
>
> Well I belive its "tell the library authors" only.
Well, you're wrong about that, as I believe I've demonstrated. But
don't worry I'll demonstrate again in a bit. If library authors do a
perfect job but they still create functions that are designed to be
found via ADL (i.e. in the same namespace as their types) users will
still need to be extra careful.
>> Actually, I'm all for that, but I want to provide a better and more
>> natural mechanism for writing code that's correct in the first
>> place.
>>
>> The problems are ultimately inherent in ADL and namespaces as they are
>> now specified, and no amount of fixing code will fix the problem. The
>> problem is that it requires too much syntax and too much thought to do
>> the right thing.
>
> I don't agree, we simply havent learnt the simple rules for writing
> C++ code with namespaces.
>
> 1 ) defenition namespaces: for related and coupled thing's.
> 2 ) Accessor namespaces: for other defenition namespaces and
> using declaration's.
I know the rules. They may be "simple" but they add complexity
syntactic weight and bookkeeping (I won't go into detail unless you
really can't see that). Many _many_ people are reluctant to use
namespaces at all; getting them to go this far is going to be hard. I
claim these people are justified in their expectation that "it ought
to be easier to do the right thing." Other languages have a much more
straightforward name lookup model, and before ADL C++ did, too.
>>>> Yes, as a library implementor you can prevent this code from
>>>> looking up the wrong copy function by paying a lot of attention and
>>>> keeping unrelated functions and data types in separate
>>>> sub-namespaces so you *could* look it as "not a core problem".
>>>
>>> I do, how is *not* defining a complety generic function like std::copy
>>> in the same namespace as completely unrelated type's "paying a lot of
>>> attention" ?
>>
>> Well, they're clearly not "completely unrelated" or we'd have no
>> problem. There's a good reason the standard library is all accessible
>> through the same namespace.
>
> Yes, but accessability doesn't require that everything accesable via
> std:: is defined there.
You don't have to explain that to me. I know what it takes to "do
the right thing" in the presence of ADL and provide the illusion of a
single namespace.
>>> Its no harder than not giving std::string a member for opening files
>>> or for adding complex numbers.
>>
>> Every time you have to consider dividing up namespaces it imposes a
>> mental burden.
>
> After the fact, If you divide first, then joining were reasonable
> and advantagous is easy.
No, dividing first has a mental cost too. It introduces layers,
names, and groupings that wouldn't otherwise be neccessary.
>> And then if you're bringing functions into type
>> namespaces with using-declarations you still need to pay attention and
>> qualify them.
>>
>> Why should functions impose this burden? You don't have to separate
>> types from one another (except as dictated by functions intended to be
>> invoked via ADL).
>
> They are different things, so different behaviours isn't
> unreasonable.
>
> Unqualified calls are ADL calls, i.e. what happens when you make an
> unqualified call is an association of function name and the argument
> types, the problem is that this isn't what we currently expect, but
This "what we currently expect" is a bit patronizing. I know what to
expect, really, or I wouldn't be making this proposal.
> there is no *fundemental* reason it shouldn't be.
No of course not. There's also no *fundemental* reason not to
program in plain 'C' or assembly language. But programming in C++
should be easier than that. If you're going to argue on the basis of
what's inherent in programming we should stop right here, because all
I'm interested in is ease-of-use (including
ease-of-doing-the-right-thing) and expressivity.
>>>> The point of the paper is that calling this a problem in the design
>>>> and implementation of std:: is asking more of library implementors
>>>> (at large) than the language should. In other words,
>>>> "consideration of the effects of ADL" is much too often neccessary.
>>>
>>> Narrower scopes (sub-namespaces) alleviate this problem.
>>
>> Yes, and users have the same problem.
>
> Only when they use libraries implemented without regard to ADL.
No. Let me demonstrate:
namespace lib
{
namespace algorithms // Do the right thing
{
template <class T>
T sqrt(T);
template <class T>
T norm(T x, unsigned kind)
{
return kind == 0 ? x < 0 ? -x : x
: kind == 1 ? sqrt(x * x)
: 0; // maybe we'd have more cases
}
template <class T>
T munge(T x)
{
return norm(x, 0); // intentionally find norm through ADL
}
}
namespace some_type_ // Do the right thing
{
class some_type {};
void f(some_type, int); // intended to be found via ADL
}
using some_type_::some_type; // Make it convenient
using some_type_::f;
using algorithms::munge;
}
namespace user
{
class foo;
void f(lib::some_type, foo*);
void g()
{ // problem #1
f(lib::some_type(), 0); // silently calls lib::f
}
struct rational
{
rational(int);
bool operator<(rational) const;
rational operator-() const;
rational operator*(rational) const;
// ...
};
int norm(rational, foo*); // unrelated function
void h(rational x)
{ // problem #2
lib::munge(x); // munge silently calls user::norm
}
}
I'm sure that if you think about it a bit you can find lots of other
cases like these.
>>>> As a library implementor, I can tell you that
>>>> paying attention to these effects is a drag on my ability to write
>>>> good code. C++ is quite complicated enough, thank you.
>>>
>>> Yes it is, but you actually want to make it more complicated:
>>>
>>> some_type a, b, c;
>>> copy( a, b, c );
>>>
>>> Currently I see the above code and know (as copy is unqualified
>>> and unparenthesized) that the call is subject to ADL.
>>>
>>> You want me to have to scan back in the TU and check wether the
>>> namespace is explicit or not and then if it is, I then have to
>>> scan for unqualified using declaration's, just to make sure.
>>
>> 1. Keeping track of which namespaces are explicit is very easy,
>> unless you have a whole mess of them. But this proposal is
>> designed to limit namespace proliferation. "Flat is better than
>> nested" (zen of python).
>
> Yes but python is also a modular language, i.e. A flat design can
> be implemented in a modular (heirarchical) fasion, we can do the
> same in C++ with nested namespaces and using declarations.
You're missing my point. What you would normally implement in a
single module in Python may have to be implemented with multiple
namespaces and using declarations. It's better to be able to flatten
those out and eliminate the complexity of using declarations.
> Give the "detail" namespcae a unique (within its scope) name and
> hoist the public interface out of it with using declaration's.
>
>>
>> 2. Unqualified using declarations should be used sparingly at
>> namespace scope, if at all. In either case, at least ADL doesn't
>> happen by accident.
>
> It *never* happens by accident
I have personally experienced it happening by accident!
> , it happens by design. If the design
> is an accident
Please. Now you're just playing word games. "By design" normally
means "not accidentally." You can't have it be "by design" when the
design is an accident.
> then either the language (*) or the design of the namespace causing
> the accident is broken.
>
> *) i.e. if ADL is wrong then it should be fixed (I'm +0 that it is
> wrong).
Wrong? Well, there's no absolute here. It's harder and more
error-prone than it should be. IMO it's in the category of things
that should be cleaned up for C++0x.
>> Understanding the meaning of any given call, even if qualified, is
>> already impossible to do with only local information. There could be
>> multiple overloads, and there could be specializations (or dispatching
>> through class template partial specializations). My proposal makes
>> that problem marginally worse in exchange for a huge reduction in
>> error-prone-ness.
>
> If I need to know in that level of detail what a function call
> does then qualification is not unreasonable IMO.
You're missing my point. Qualification doesn't help very much in
reality.
>>> Also isn't dealing with these kind of details one of the
>>> reason's libraries exist, the library author does it so the
>>> end user doesn't have too.
>>
>> The user has the same problems the library author has. Any careless
>> unqualified call might pick up a library function. Even if libraries
>> are all subdivided as you propose, it can pick up one of the
>> functions intended for ADL.
>
> As it should IMO, but then I like ADL (I may be the only one :).
First you claimed that users can't get in trouble by not separating
functions and classes when the libraries are written properly. Now it
sounds like you're saying the poor users deserve whatever they get.
>>> Your're proposal (kind of) implies: No library authors should
>>> just write blob namespace libraries and the language and the
>>> *user* should deal with it.
>>
>> ?? My proposal would make it possible for the user to worry much
>> less about these things.
>
> Do users (*) worry about such thing's now ?
If they want to do it right they do.
> *) users != library implementors using other libraries.
Creating an arbitrarily higher standard for library implementors and
users is also bad for the future of the language.
>>> I don't mind the language dealing with it, I do object to the
>>> user having too.
>>
>> I haven't a clue what you're referring to.
>
> The complexity for users increases with this proposal, more
> expertise not less (or the same) is required of them.
It depends. When we get to the point where all namespaces are
explicit, it'll be simpler.
>>>> It is a fact that if you intend to call a function in your own
>>>> namespace, you'd better use a qualified call.
>>>
>>> Yes, a unique function needs a unique name, its unfortunate that
>>> std::copy doesn't
>>
>> doesn't what? need a unique name? (??)
>>::std::copy certainly is a unique name, so I don't see what you're
>> getting at.
>
> All function's have a fully qualified unique name, some (std::copy
> included) are also accesable via ADL using ther short name, std::copy
> shouldn't be such a function, it should only be accesable with its
> fully qualified name or via a using declaration/statement.
Agreed.
>>> If I had a time machine I'd go back and suggest that ADL be
>>> explicitly enabled (maybe overload the meaning of friend or
>>> operator), then std::copy et al would be what they were
>>> intended to be in the first place, function's that are called
>>> fully qualified or when there names have been hoisted into scope.
>>>
>>> But its unlikely I'll ever get that, so how about:
>>>
>>> namespace std
>>> {
>>> template < ... >
>>> explicit ... copy( ... );
>>> }
>>>
>>> It worked for (i.e. disabled) unintended converting ctor's.
>>
>> I assume you want the addition of "explicit" to change the way copy
>> is looked up here?
>
> Yep.
>
>>
>> Well, it's not a bad idea, but it doesn't solve the same problems
>> unless everyone does it (users too). New lookup rules within an
>> explicit namespace prevent *any* copy(...) from being unintentionally
>> found via ADL. Ultimately your suggestion adds too much syntactic
>> noise in my opinion.
>
> I see your POV, but I would see this change as handy feature I would
> occasionaly use, you (I suspect) see this as somthing you would need
> to use all the time, hence a noisy feature.
Yep. Not just syntactically but mentally. I want to take ADL *out*
of the sequence of mental gymnastics required of someone writing code
unless explicitly requested. Also I consider the fact that
qualification or parentheses are needed to reliably call a function in
the same namespace without other overloads being found by ADL to be
perverse. No matter how much I think about this (and I think about it
a lot), I constantly find places where I've left out the
qualification. To date, only very occasional problems actually
manifest themselves -- but I actually see that as rather a bad sign.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Stephen Lamb <slamb@easystreet.com>
Date: Sat, 25 Sep 2004 00:08:44 +0000 (UTC) Raw View
"David Abrahams" <dave@boost-consulting.com> wrote in message
news:uwtyrd8cm.fsf@boost-consulting.com...
>
>
> The committee's Pre-Redmond mailing is out; you can peruse the papers
> at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004. For
> anyone interested in N1691, "Explicit Namespaces", an administrative
> SNAFU seems to have mangled it. A pristine version is available at
> http://www.boost-consulting.com/writing/n1691.html
I'm not sure if you meant to leave off the return type in the declaration of
tie in example 2. This shows up in both places mentioned above.
// Connect p2 to the output of p1
tie(pipe const& p1, pipe& p2);
Did you mean?
// Connect p2 to the output of p1
void tie(pipe const& p1, pipe& p2);
Not that this matters a whole lot to your points.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: David Abrahams <dave@boost-consulting.com>
Date: Sun, 19 Sep 2004 22:54:41 +0000 (UTC) Raw View
The committee's Pre-Redmond mailing is out; you can peruse the papers
at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004. For
anyone interested in N1691, "Explicit Namespaces", an administrative
SNAFU seems to have mangled it. A pristine version is available at
http://www.boost-consulting.com/writing/n1691.html
Cheers,
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Mon, 20 Sep 2004 14:09:45 GMT Raw View
David Abrahams wrote in news:uwtyrd8cm.fsf@boost-consulting.com in
comp.lang.c++.moderated:
xpost to clc++ and clc++m cancelled.
>
> The committee's Pre-Redmond mailing is out; you can peruse the papers
> at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004. For
> anyone interested in N1691, "Explicit Namespaces", an administrative
> SNAFU seems to have mangled it. A pristine version is available at
> http://www.boost-consulting.com/writing/n1691.html
>
Possible typo
-------------
explicit namespace new_std::
(3 A Solution / II) is the :: intentional.
Motivating Examples
-------------------
In your first example from the link above:
<http://www.boost-consulting.com/writing/n1691.html#problem-1-unintended-
overloading>
#include <vector>
namespace user
{
typedef std::vector<Customer*> index;
// copy an index, selecting deep or shallow copy for Customers
void copy(index const&, index&, bool deep);
void g(index const& x)
{
copy(x, x, false);
}
}
The problem above *isn't* a core language problem, its that std::copy
(and indeed the whole std namespace) was designed and implemented (quite
understandably IMO) without any consideration of the effects of ADL.
namespace std
{
namespace algoritms /* or detail or whatever */
{
template < ... > ... copy( ... )
{
/* for loop here */
}
}
using algoritms::copy;
}
The above would IMO fix more future code than it would brake
existing code.
Your 2nd example has the same problem, std::tr1::tie has no
association with std::tr1::shared_ptr, so it shouldn't be
declared/defined in the same namespace.
Your fact:
When calling functions in her own namespace, a conscientious
programmer must disable ADL by using qualified calls.
needs rewriting (i.e. I don't agree that it is a fact):
My "Fact":
Library authors [1]_ need to be ADL aware.
.. [1] Indeed authors of any piece of reusable code, which is
hopefully the majority of C++ programmers :).
std::swap
---------
The problem with std::swap, is a pre-ADL design/specification/usage
problem, it needs respecifying:
namespace std
{
template < typename T >
typename enable_if< has_swap_member< T > >::type
swap( T &left, T &right )
{
left.swap( right );
}
template < typename T >
typename disable_if< has_swap_member< T > >::type
swap( T &left, T &right )
{
T temp = left;
left = right;
right = left;
}
}
Usage:
#include <algorithm>
template < typename T >
void f()
{
T a, b; /* initialzed ? */
using std::swap; /* inbuilt/POD and backward compatibility */
swap( a, b ); /* ADL / has_swap_member / inbuilt's-etc */
}
Its only for backward compatibilty that I didn't (re) define std::swap
in std::algorithms:: as I did with std::copy above. I.e. I think class
authors should provide there own ADL findable swap and *not* specialize
or overload std::swap.
ADL-is-here-to-help-ly yr's Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Tue, 21 Sep 2004 01:02:20 GMT Raw View
rtw@freenet.co.uk (Rob Williscroft) writes:
> David Abrahams wrote in news:uwtyrd8cm.fsf@boost-consulting.com in
> comp.lang.c++.moderated:
>
> xpost to clc++ and clc++m cancelled.
>
>>
>> The committee's Pre-Redmond mailing is out; you can peruse the papers
>> at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004. For
>> anyone interested in N1691, "Explicit Namespaces", an administrative
>> SNAFU seems to have mangled it. A pristine version is available at
>> http://www.boost-consulting.com/writing/n1691.html
>>
>
> Possible typo
> -------------
>
> explicit namespace new_std::
> (3 A Solution / II) is the :: intentional.
Yeah, that's a mistake left over from a previous version of the paper
(which you can find a link to at the site above if you care). Pretend
the "::" wasn't there.
> Motivating Examples
> -------------------
>
> In your first example from the link above:
>
> <http://www.boost-consulting.com/writing/n1691.html#problem-1-unintended-
> overloading>
>
> #include <vector>
>
> namespace user
> {
> typedef std::vector<Customer*> index;
>
> // copy an index, selecting deep or shallow copy for Customers
> void copy(index const&, index&, bool deep);
>
> void g(index const& x)
> {
> copy(x, x, false);
> }
> }
>
> The problem above *isn't* a core language problem, its that std::copy
> (and indeed the whole std namespace) was designed and implemented (quite
> understandably IMO) without any consideration of the effects of ADL.
You seem to have completely missed the point of the paper. Yes, as a
library implementor you can prevent this code from looking up the
wrong copy function by paying a lot of attention and keeping unrelated
functions and data types in separate sub-namespaces so you *could*
look it as "not a core problem". The point of the paper is that
calling this a problem in the design and implementation of std:: is
asking more of library implementors (at large) than the language
should. In other words, "consideration of the effects of ADL" is much
too often neccessary. As a library implementor, I can tell you that
paying attention to these effects is a drag on my ability to write
good code. C++ is quite complicated enough, thank you.
> namespace std
> {
> namespace algoritms /* or detail or whatever */
> {
> template < ... > ... copy( ... )
> {
> /* for loop here */
> }
> }
> using algoritms::copy;
> }
>
> The above would IMO fix more future code than it would brake
> existing code.
Yes of course we can solve this specific problem that way -- and it's
probably a good change to make. But it doesn't solve the larger
problem.
> Your 2nd example has the same problem, std::tr1::tie has no
> association with std::tr1::shared_ptr, so it shouldn't be
> declared/defined in the same namespace.
>
> Your fact:
>
> When calling functions in her own namespace, a conscientious
> programmer must disable ADL by using qualified calls.
>
> needs rewriting (i.e. I don't agree that it is a fact):
Well, it's not going to be rewritten; I meant exactly what I wrote.
It is a fact that if you intend to call a function in your own
namespace, you'd better use a qualified call. Unless the code is
going to be frozen for all time and the argument types will never
change in ways you didn't anticipate, you have to do it to prevent
unintended consequences down the road when the code is maintained.
> My "Fact":
>
> Library authors [1]_ need to be ADL aware.
>
> .. [1] Indeed authors of any piece of reusable code, which is
> hopefully the majority of C++ programmers :).
Whatever. That's a problem in and of itself.
> std::swap
> ---------
>
> The problem with std::swap, is a pre-ADL design/specification/usage
> problem, it needs respecifying:
>
> namespace std
> {
> template < typename T >
> typename enable_if< has_swap_member< T > >::type
> swap( T &left, T &right )
> {
> left.swap( right );
> }
>
> template < typename T >
> typename disable_if< has_swap_member< T > >::type
> swap( T &left, T &right )
> {
> T temp = left;
> left = right;
> right = left;
> }
> }
Whatever again. That's an _entirely_ different issue than what the
paper is addressing. If you want to propose that, write your own
paper.
> Usage:
>
> #include <algorithm>
>
> template < typename T >
> void f()
> {
> T a, b; /* initialzed ? */
>
> using std::swap; /* inbuilt/POD and backward compatibility */
> swap( a, b ); /* ADL / has_swap_member / inbuilt's-etc */
> }
>
> Its only for backward compatibilty that I didn't (re) define std::swap
> in std::algorithms:: as I did with std::copy above. I.e. I think class
> authors should provide there own ADL findable swap and *not* specialize
> or overload std::swap.
>
> ADL-is-here-to-help-ly yr's Rob.
like-the-paperclip-in-ms-word-only-more-dangerous-ly y'rs,
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Howard Hinnant <hinnant@metrowerks.com>
Date: Mon, 20 Sep 2004 23:27:04 CST Raw View
In article <Xns956A994F9F4C7ukcoREMOVEfreenetrtw@130.133.1.4>,
rtw@freenet.co.uk (Rob Williscroft) wrote:
> std::swap
> ---------
>
> The problem with std::swap, is a pre-ADL design/specification/usage
> problem, it needs respecifying:
>
> namespace std
> {
> template < typename T >
> typename enable_if< has_swap_member< T > >::type
> swap( T &left, T &right )
> {
> left.swap( right );
> }
>
> template < typename T >
> typename disable_if< has_swap_member< T > >::type
> swap( T &left, T &right )
> {
> T temp = left;
> left = right;
> right = left;
> }
> }
At one time I thought this was a good idea. Indeed I think it probably
would've been a good idea had we known how to do it in '97 or '98. But
now I worry about silently breaking this reasonable code:
namespace MySpace
{
struct MyClass
{
char a, b, c, d;
void swap(MyClass& x) {std::swap(*this, x);}
};
inline void swap(MyClass& x, MyClass& y)
{
x.swap(y);
}
} // MySpace
The author of MyClass would like clients to be able to swap MyClass's
easily, even if they call swap unqualified and forget to add a "using
std::swap". So even though MyClass::swap does nothing special, it is
included as part of the interface as a convenience.
However, since it does nothing special, it relies on std::swap for the
actual implementation. This is quite likely to generate superior code
than calling swap on each of MyClass's members individually.
Alternatively MyClass could have repeated the std::swap algorithm, but
reusing the std::code seems not only convenient and harmless, but
actually elegant.
The above MyClass is not only reasonable, but is actually good C++03
code.
However if we change swap as you suggest, then MyClass::swap now
silently changes into infinite recursion.
-Howard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Ioannis Vranos <ivr@guesswh.at.grad.com>
Date: Tue, 21 Sep 2004 16:30:29 +0000 (UTC) Raw View
David Abrahams wrote:
>
> The committee's Pre-Redmond mailing is out; you can peruse the papers
> at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004. For
> anyone interested in N1691, "Explicit Namespaces", an administrative
> SNAFU seems to have mangled it. A pristine version is available at
> http://www.boost-consulting.com/writing/n1691.html
The long long issue, although in C99 and C++/CLI current draft, I think
it must become long64 or int64.
--
Ioannis Vranos
http://www23.brinkster.com/noicys
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: technews@kangaroologic.com ("Jonathan Turkanis")
Date: Tue, 21 Sep 2004 17:36:46 GMT Raw View
"David Abrahams" <dave@boost-consulting.com> wrote in message
news:uwtyrd8cm.fsf@boost-consulting.com...
>
>
> The committee's Pre-Redmond mailing is out; you can peruse the papers
> at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004. For
> anyone interested in N1691, "Explicit Namespaces", an administrative
> SNAFU seems to have mangled it. A pristine version is available at
> http://www.boost-consulting.com/writing/n1691.html
I'm very pleased with your new version of this proposal. I found the notation in
the previous version so awkward that I had trouble imagining it ever being
adopted. I tried to think of alternate notation, but the best I could do was
namespace std [ ... ]
:-D
You've resolved this problem nicely -- 'explicit' is actually a pretty good
description, even if you could choose a new keyword freely.
BTW, section 2.3 contains an seemingly mangled sentence: "Since they are
perfectly easy, and will unintended ADL will pass unnoticed through all but the
most sadistic tests, there is little incentive other than good conscience to add
qualification."
Jonathan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ben-public-nospam@decadentplace.org.uk (Ben Hutchings)
Date: Wed, 22 Sep 2004 17:06:53 GMT Raw View
Rob Williscroft wrote:
<snip>
> The problem with std::swap, is a pre-ADL design/specification/usage
> problem, it needs respecifying:
>
> namespace std
> {
> template < typename T >
> typename enable_if< has_swap_member< T > >::type
> swap( T &left, T &right )
> {
> left.swap( right );
> }
>
> template < typename T >
> typename disable_if< has_swap_member< T > >::type
> swap( T &left, T &right )
> {
> T temp = left;
> left = right;
> right = left;
> }
> }
<snip>
That just makes "swap" effectively a reserved name in all class scopes
rather than in all namespace scopes. How is that an improvement?
--
Ben Hutchings
The generation of random numbers is too important to be left to chance.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rtw@freenet.co.uk (Rob Williscroft)
Date: Wed, 22 Sep 2004 17:14:15 GMT Raw View
David Abrahams wrote in news:u1xgw38mq.fsf@boost-consulting.com in
comp.std.c++:
>> The problem above *isn't* a core language problem, its that std::copy
>> (and indeed the whole std namespace) was designed and implemented
>> (quite understandably IMO) without any consideration of the effects
>> of ADL.
>
> You seem to have completely missed the point of the paper.
Well maybe so, but that doesn't matter, I didn't miss: "a different kind
of namespace with new lookup rules". What you're proposing to change
is more important than why you want to change it.
FWIW I belive the point (of the explicit namespace part at least) is to
enable libraries to be writen as they are by many people now but without
ADL problem's, a laudable goal I approve of I just don't approve of the
mechanism. I'd much rather other libraries didn't cause the problem's in
the first place.
> Yes, as a
> library implementor you can prevent this code from looking up the
> wrong copy function by paying a lot of attention and keeping unrelated
> functions and data types in separate sub-namespaces so you *could*
> look it as "not a core problem".
I do, how is *not* defining a complety generic function like std::copy
in the same namespace as completely unrelated type's "paying a lot of
attention" ? Its no harder than not giving std::string a member for
opening files or for adding complex numbers.
> The point of the paper is that
> calling this a problem in the design and implementation of std:: is
> asking more of library implementors (at large) than the language
> should. In other words, "consideration of the effects of ADL" is much
> too often neccessary.
Narrower scopes (sub-namespaces) alleviate this problem.
> As a library implementor, I can tell you that
> paying attention to these effects is a drag on my ability to write
> good code. C++ is quite complicated enough, thank you.
Yes it is, but you actually want to make it more complicated:
some_type a, b, c;
copy( a, b, c );
Currently I see the above code and know (as copy is unqualified
and unparenthesized) that the call is subject to ADL.
You want me to have to scan back in the TU and check wether the
namespace is explicit or not and then if it is, I then have to
scan for unqualified using declaration's, just to make sure.
Also isn't dealing with these kind of details one of the
reason's libraries exist, the library author does it so the
end user doesn't have too.
Your're proposal (kind of) implies: No library authors should
just write blob namespace libraries and the language and the
*user* should deal with it.
I don't mind the language dealing with it, I do object to the
user having too.
>
>> namespace std
>> {
>> namespace algoritms /* or detail or whatever */
>> {
>> template < ... > ... copy( ... )
>> {
>> /* for loop here */
>> }
>> }
>> using algoritms::copy;
>> }
>>
>> The above would IMO fix more future code than it would brake
>> existing code.
>
> Yes of course we can solve this specific problem that way -- and it's
> probably a good change to make. But it doesn't solve the larger
> problem.
>
>> Your 2nd example has the same problem, std::tr1::tie has no
>> association with std::tr1::shared_ptr, so it shouldn't be
>> declared/defined in the same namespace.
>>
>> Your fact:
>>
>> When calling functions in her own namespace, a conscientious
>> programmer must disable ADL by using qualified calls.
>>
>> needs rewriting (i.e. I don't agree that it is a fact):
>
> Well, it's not going to be rewritten; I meant exactly what I wrote.
Never thought otherwise.
> It is a fact that if you intend to call a function in your own
> namespace, you'd better use a qualified call.
Yes, a unique function needs a unique name, its unfortunate that
std::copy doesn't as its associated with types with which it has
no relation.
> Unless the code is
> going to be frozen for all time and the argument types will never
> change in ways you didn't anticipate, you have to do it to prevent
> unintended consequences down the road when the code is maintained.
>
And if you do that, you do it at one place, the call site, with
qualification or parentheses, maintainers don't have to analyze
the whole TU inorder to see what is going on.
Still its a cure not pervention.
If I had a time machine I'd go back and suggest that ADL be
explicitly enabled (maybe overload the meaning of friend or
operator), then std::copy et al would be what they were
intended to be in the first place, function's that are called
fully qualified or when there names have been hoisted into scope.
But its unlikely I'll ever get that, so how about:
namespace std
{
template < ... >
explicit ... copy( ... );
}
It worked for (i.e. disabled) unintended converting ctor's.
Either way I don't want more complicated lookup rules,
particularly two sets of them.
Rob.
--
http://www.victim-prime.dsl.pipex.com/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]