Topic: [C++0x] Methods vs global functions
Author: "Balog Pal" <pasa@lib.hu>
Date: 14 Jun 01 01:37:15 GMT Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message news:+tHK3uADsuG7EwBd@ntlworld.com...
> Yes. But an earlier poster has already been more explicit. The change
> takes place if this 'extension' was allowed and the class owner adds to
> the interface a function whose name matches that which a user has used.
I see nothing new in this breakdown. If you have a
void foo(long);
and use it:
foo(1);
then someone adds a new function, void foo(int) in one of the headers you
happen to include, and your code will call it instead of the old one.
Having a 1% increase to the places where such a function can be
introduced doesn's seem like a big deal to me. And considering the
current way operators work, I think the proposal under discussion is a
very good one, I'd enjoy to have it implemented together with the dangers.
Paul
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: quux111@newsguy.com (quux111)
Date: 07 Jun 01 02:32:41 GMT Raw View
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in
news:9emamh$57p4$1@ID-14036.news.dfncis.de:
><SNIP>
>
> Perhaps using inheritance just to add convenience member functions is
> the worst, most gruesome, form of abuse of inheritance.
>
>
> Andrei
>
><SNIP sig>
Hear hear. That's been my biggest gripe about C++ for a long time -- there
seems to be a "traditionalist" mindset that the only way to extend a class
is by modifying the class itself or by inheritance. As Andrei said, Blech.
Instead, I often implement an SBA (service-based architecture) layer.
Example:
class HelperClass
{
public:
UtilityMethodA();
UtilityMethodB();
};
class Foo
{
private:
HelperClass *helper; // this only gets instantiated if used
public:
Foo();
};
As you can see, HelperClass is only instantiated if used. HelperClass can
also be extended without breaking classes that use it, as long as the
interface is only *extended* (i.e., the existing methods are not changed).
This is certainly not a new or original idea, but it works well for me and
allows me to create much more flexible classes.
quux111
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: news/comp.std.c++@nmhq.net (Niklas Matthies)
Date: 5 Jun 2001 14:43:06 -0400 Raw View
On 05 Jun 01 06:54:11 GMT, James Kuyper <kuyper@wizard.net> wrote:
> Niklas Matthies wrote:
> > On 04 Jun 01 05:53:47 GMT, Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
[ ]
> > > >I'm not sure I follow you. The only case where the meaning of
> > > >code could change its meaning is 3 (because 2 results in the
> > > >present meaning), but code that falls under 3 does currently not
> > > >compile. Hence only code that is not conforming under C++98 would
> > > >get a new meaning (a meaning at all, more precisely). Or am I
> > > >missing something?
> > >
> > > Yes. But an earlier poster has already been more explicit. The
> > > change takes place if this 'extension' was allowed and the class
> > > owner adds to the interface a function whose name matches that
> > > which a user has used.
> >
> > This isn't too different from adding a virtual member function to a
> > base class where some derived class previously introduced a member
> > function with the same name.
>
> It isn't very different, but the small difference that there is, is
> crucial. The writer of a class with a virtual member function expects
> that function to be overridden; this affects even functions that
> weren't virtual.
Well, that isn't very convincing, because we are discussing the case
where the overriding member function in the derived class has been
written prior to the overridden member function in the base class, hence
the former wasn't written as a member function suitable for overriding
some member function of the base class (with has unknown semantics at
the time of writing the overriding function), and yet it suddenly serves
as an overriding member function for the newly-introduced base-class
member function, quite likely wrecking havoc because base-class callers
expect it to have different semantics than it probably has.
In this sense, this situation very much parallels the proposal made in
this thread. In fact, the situation with virtual member functions could
be considered to be worse, because the caller that calls the overriding
member function through a base-class reference can reside in a separate
compilation unit which cannot be aware of the overriding member
function, whereas the proposal only has side-effects within the same
compilation unit. The proposal also doesn't affect code that calls the
member function being overridden, whereas the presence of an overriding
member function affects code that calls the (virtual) base-class member
function that is being overridden. Furthermore, it doesn't make sense to
warn about the overriding of a virtual member function, but it makes
some sense to warn about the overriding of a member function with a
global function, hence the latter is less likely to go unnoticed.
The fact that apparently in practice the above case isn't much of a
problem could be taken as an indication that implementing the proposal
won't be much of a practical problem as well.
-- Niklas Matthies
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 05 Jun 01 21:02:55 GMT Raw View
In article <3B1BBC49.20CCAC70@wizard.net>, James Kuyper
<kuyper@wizard.net> writes
>> > Yes. But an earlier poster has already been more explicit. The change
>> > takes place if this 'extension' was allowed and the class owner adds to
>> > the interface a function whose name matches that which a user has used.
>>
>> This isn't too different from adding a virtual member function to a base
>> class where some derived class previously introduced a member function
>> with the same name.
>
>It isn't very different, but the small difference that there is, is
>crucial. The writer of a class with a virtual member function expects
>that function to be overridden; this affects even functions that weren't
>virtual.
IMO, adding virtual functions to an already published class is always
suspect. What is even worse is that even adding private virtual
functions can have unforeseen consequences. But most of us know that the
'virtual' keyword can be dangerous and treat it with care. What is being
proposed here is much broader because it breaks encapsulation.
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Chris Lattner<sabre@nondot.org>
Date: 4 Jun 2001 17:32:32 -0400 Raw View
In comp.lang.c++.moderated Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
>>code that falls under 3 does currently not compile. Hence only code that
>>is not conforming under C++98 would get a new meaning (a meaning at all,
>>more precisely). Or am I missing something?
> Yes. But an earlier poster has already been more explicit. The change
> takes place if this 'extension' was allowed and the class owner adds to
> the interface a function whose name matches that which a user has used.
In such a case, the c++ compiler would be able to detect the potential
ambiguity, and would emit a diagnostic (if not an error), as it already
does in the face of other ambiguities. Thus, it would not silently break
existing code, or code extended in the future...
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 4 Jun 2001 17:34:58 -0400 Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20010602150334.21899B@brangdon.madasafish.com...
> You seem to be agreeing with Matvei Brodski that the f(o) half of the
> proposal is unnecessary, and arguing for the o.f(). My own position is
> roughly the opposite (although I think either half would be too big a
> language change at this stage). One advantage of f(o) is that code using
> it can be made backward compatible.
To make things clear: I agree with you. Gee, I forgot to take my English
pills lately :o).
Andrei
--
Check out THE C++ Seminar: 3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 05 Jun 01 06:54:11 GMT Raw View
Niklas Matthies wrote:
>
> On 04 Jun 01 05:53:47 GMT, Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> > In article <slrn9hkiaf.qv.news/comp.std.c++@ns.nmhq.net>, Niklas
> > Matthies <news/comp.std.c++@nmhq.net> writes
> > >I'm not sure I follow you. The only case where the meaning of code could
> > >change its meaning is 3 (because 2 results in the present meaning), but
> > >code that falls under 3 does currently not compile. Hence only code that
> > >is not conforming under C++98 would get a new meaning (a meaning at all,
> > >more precisely). Or am I missing something?
> >
> > Yes. But an earlier poster has already been more explicit. The change
> > takes place if this 'extension' was allowed and the class owner adds to
> > the interface a function whose name matches that which a user has used.
>
> This isn't too different from adding a virtual member function to a base
> class where some derived class previously introduced a member function
> with the same name.
It isn't very different, but the small difference that there is, is
crucial. The writer of a class with a virtual member function expects
that function to be overridden; this affects even functions that weren't
virtual.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Jake Holland" <jholland@ixiacom.com>
Date: 5 Jun 2001 06:01:13 -0400 Raw View
"Bruce G. Stewart" <bruce.g.stewart@worldnet.att.net> wrote in message
news:3B1AF11F.4E994094@worldnet.att.net...
<snip>
>
> Yet somehow this is acceptable for operator functions and member
> functions.
>
> cout << i;
>
> cout::operator <<(int) or operator <<(iosomething, int) ?
>
> Only the implementor knows for sure, which is possibly how it should be.
Even the implementor often doesn't know for sure, if he's modifying existing
code. In a large project it's not easy to make sure that when you add
operator member functions, you're not breaking some other operator that's
already out there. IMHO, this is one of the most frightening things about
using operators, and I never feel safe when I do it. I don't know what I'd
do if I had to worry about this for all named functions, too.
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 05 Jun 01 13:47:40 GMT Raw View
In article <3B1AF11F.4E994094@worldnet.att.net>, Bruce G. Stewart
<bruce.g.stewart@worldnet.att.net> writes
>Yet somehow this is acceptable for operator functions and member
>functions.
>
>cout << i;
>
>cout::operator <<(int) or operator <<(iosomething, int) ?
Except that, by using the function syntax it is possible to select
either free or a member operator (function) and this proposal would
mean that even this would not be possible.
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Pete Becker <petebecker@acm.org>
Date: 06 Jun 01 07:49:22 GMT Raw View
Niklas Matthies wrote:
>
> On 05 Jun 01 06:54:11 GMT, James Kuyper <kuyper@wizard.net> wrote:
> > Niklas Matthies wrote:
> > > On 04 Jun 01 05:53:47 GMT, Francis Glassborow
<francis.glassborow@ntlworld.com> wrote:
> [ ]
> > > > >I'm not sure I follow you. The only case where the meaning of
> > > > >code could change its meaning is 3 (because 2 results in the
> > > > >present meaning), but code that falls under 3 does currently not
> > > > >compile. Hence only code that is not conforming under C++98 would
> > > > >get a new meaning (a meaning at all, more precisely). Or am I
> > > > >missing something?
> > > >
> > > > Yes. But an earlier poster has already been more explicit. The
> > > > change takes place if this 'extension' was allowed and the class
> > > > owner adds to the interface a function whose name matches that
> > > > which a user has used.
> > >
> > > This isn't too different from adding a virtual member function to a
> > > base class where some derived class previously introduced a member
> > > function with the same name.
> >
> > It isn't very different, but the small difference that there is, is
> > crucial. The writer of a class with a virtual member function expects
> > that function to be overridden; this affects even functions that
> > weren't virtual.
>
> Well, that isn't very convincing, because we are discussing the case
> where the overriding member function in the derived class has been
> written prior to the overridden member function in the base class, hence
> the former wasn't written as a member function suitable for overriding
> some member function of the base class (with has unknown semantics at
> the time of writing the overriding function), and yet it suddenly serves
> as an overriding member function for the newly-introduced base-class
> member function, quite likely wrecking havoc because base-class callers
> expect it to have different semantics than it probably has.
>
The difference is in encapsulation. When the interface to a base class
is changed anyone who uses it must review their code to be sure that the
changes won't cause problems. If problems like this can arise only in
derived classes then you only have to check the headers that define the
derived classes. If conflicts can arise from non-member functions then
you have to check every source file.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Jake Holland" <jholland@ixiacom.com>
Date: 03 Jun 01 08:56:27 GMT Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:AxnFwuAOSiF7EweE@ntlworld.com...
[snip]
>
> class X {
> public void algo();
> ...
> }
>
> algo() applies some algorithm to instances of X. Now I come along and
> note that I can provide that functionality in a different way that works
> better for my purposes so I write:
>
> namespace mywork {
> void algo(X &);
> }
>
> Now you come along and change the language so that my version behaves
> like a member function. Now, all my already written code falls over (at
> least noisily in this instance)
>
> Scope issues are very important in a context of overloading function
> names, think about it (saves me having to bore everyone with long
> screeds of detail). We are not designing a new language but attempting
> to refine an already widely used one.
>
I have to say I think this is an incredibly good point, and provides an
excellent argument against changing the language. I'd like to mention a
similar point which would make me, personally, run screaming from any
situation in which I would be forced to use some "extended" version of the
language that did have such syntax:
Suppose I'm not allowed to add something to a class interface, so I create a
global function that acts on my object type and uses only public methods and
whatever else the OP on this thread stipulated. Now somebody else who is
allowed to improve this class (maybe it's in a library that's under
construction by another group) comes along and adds an apparently innocuous
member function that happens to have the same name which does something
almost, but not quite, entirely unlike my global function.
Bang.
That noise was me shooting myself in the head because all my code stopped
working. It seems to me that this language extension would make it
impossible to ever safely extend any library of classes, for fear of
breaking client code by adding member functions. Am I misinterpreting the
consequences?
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: 03 Jun 01 08:57:16 GMT Raw View
andrewalex@hotmail.com (Andrei Alexandrescu) wrote (abridged):
> > > > we can easily add global foo (even put it in the same namespace
> > > > for Koenig's sake) if we do not want to use "dot":
> > >
> > > I agree. I also hope you agree that the maintenance burden for that
> > > minor convenience would be too big.
> >
> > Are you saying it is OK for every function signature to have to be
> > written 4 times?
>
> Hey, I said "BIG" maintenance burden.
I had trouble figuring out what you meant. Hence my question.
I suppose I don't think the convenience is minor. It is a matter of
compile-time polymorphism. It's important. We shouldn't have to replicate
functions to get it.
You seem to be agreeing with Matvei Brodski that the f(o) half of the
proposal is unnecessary, and arguing for the o.f(). My own position is
roughly the opposite (although I think either half would be too big a
language change at this stage). One advantage of f(o) is that code using
it can be made backward compatible.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 03 Jun 01 08:57:40 GMT Raw View
In article <%fyR6.8061$ki5.110502@vixen.cso.uiuc.edu>, Chris Lattner
<sabre@nondot.org> writes
>In the document, I propose an entirely backwards compatible way of doing this
>that would be relatively safe and simple to implement: only try to match the
>other form if no match can be found. Thus the name lookup rules would look
>like this:
>
>1. Try normal stuff
>2. If match found, use it
>3. If no match found
> 3a. Try using method or nonmethod syntax as appropriate, duplicating name
> lookup stages from step 1.
> 3b. If match found, use it.
> 3c. If no match found, bail out.
The potential for (silently) changing the meaning of code is staggering.
I thought people wanted more, not less, safety
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: 3 Jun 2001 12:57:02 -0400 Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote (abridged):
> Now you come along and change the language so that my version
behaves
> like a member function. Now, all my already written code falls over
(at
> least noisily in this instance)
In one version of the proposal, the member function would only match
the global call syntax if no global function declaration was found.
That means the behaviour of existing code would not change. No old
programs would fail to compile.
Another approach would be to make the new call syntax optional,
switched off by default. Eg:
class Demo {
public:
void member();
};
void test() {
Demo demo;
member( demo ); // Compile error.
using class Demo;
member( demo ); // OK!
}
Here the using-directive is what enables the new call syntax, just for
one specific class in one specific scope.
Admittedly this is somewhat twisted. The "using" keyword is currently
my favourite for being given new and creative meanings. In a few years
it could rival "static" :-) Anyway, this just shows that backwards
compatibility is not a killer objection, if we really want the new
call syntax.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: news/comp.std.c++@nmhq.net (Niklas Matthies)
Date: 3 Jun 2001 15:31:28 -0400 Raw View
On 03 Jun 01 08:57:40 GMT, Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <%fyR6.8061$ki5.110502@vixen.cso.uiuc.edu>, Chris Lattner
> <sabre@nondot.org> writes
> >In the document, I propose an entirely backwards compatible way of doing this
> >that would be relatively safe and simple to implement: only try to match the
> >other form if no match can be found. Thus the name lookup rules would look
> >like this:
> >
> >1. Try normal stuff
> >2. If match found, use it
> >3. If no match found
> > 3a. Try using method or nonmethod syntax as appropriate, duplicating name
> > lookup stages from step 1.
> > 3b. If match found, use it.
> > 3c. If no match found, bail out.
>
> The potential for (silently) changing the meaning of code is staggering.
> I thought people wanted more, not less, safety
I'm not sure I follow you. The only case where the meaning of code could
change its meaning is 3 (because 2 results in the present meaning), but
code that falls under 3 does currently not compile. Hence only code that
is not conforming under C++98 would get a new meaning (a meaning at all,
more precisely). Or am I missing something?
-- Niklas Matthies
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 04 Jun 01 05:53:47 GMT Raw View
In article <slrn9hkiaf.qv.news/comp.std.c++@ns.nmhq.net>, Niklas
Matthies <news/comp.std.c++@nmhq.net> writes
>I'm not sure I follow you. The only case where the meaning of code could
>change its meaning is 3 (because 2 results in the present meaning), but
>code that falls under 3 does currently not compile. Hence only code that
>is not conforming under C++98 would get a new meaning (a meaning at all,
>more precisely). Or am I missing something?
Yes. But an earlier poster has already been more explicit. The change
takes place if this 'extension' was allowed and the class owner adds to
the interface a function whose name matches that which a user has used.
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Bruce G. Stewart" <bruce.g.stewart@worldnet.att.net>
Date: 4 Jun 2001 12:52:29 -0400 Raw View
Francis Glassborow wrote:
>
> In article <CQVQ6.7750$ki5.106354@vixen.cso.uiuc.edu>, Chris Lattner
> <sabre@nondot.org> writes
> >The problem is that people currently PREFER to write in the o.foo()
> >form, but are sometimes REQUIRED to write in the foo(o) form. I am
> >not proposing banning anything: we already have two forms. What I
> >am proposing is that we unify the symantic equilivence by making
> >them syntactically equilivent.
>
> And you entirely miss the point that this causes major problems with
> name lookup. Those of us who have been around these issues for the last
> decade know just how fragile that area is. o.foo() and foo(o) specify
> entirely different scopes for lookup and any attempt to combine them
> would be a nest of vipers.
Yet somehow this is acceptable for operator functions and member
functions.
cout << i;
cout::operator <<(int) or operator <<(iosomething, int) ?
Only the implementor knows for sure, which is possibly how it should be.
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: news/comp.std.c++@nmhq.net (Niklas Matthies)
Date: 4 Jun 2001 12:54:34 -0400 Raw View
On 04 Jun 01 05:53:47 GMT, Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
> In article <slrn9hkiaf.qv.news/comp.std.c++@ns.nmhq.net>, Niklas
> Matthies <news/comp.std.c++@nmhq.net> writes
> >I'm not sure I follow you. The only case where the meaning of code could
> >change its meaning is 3 (because 2 results in the present meaning), but
> >code that falls under 3 does currently not compile. Hence only code that
> >is not conforming under C++98 would get a new meaning (a meaning at all,
> >more precisely). Or am I missing something?
>
> Yes. But an earlier poster has already been more explicit. The change
> takes place if this 'extension' was allowed and the class owner adds to
> the interface a function whose name matches that which a user has used.
This isn't too different from adding a virtual member function to a base
class where some derived class previously introduced a member function
with the same name.
-- Niklas Matthies
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Chris Lattner<sabre@nondot.org>
Date: 31 May 01 11:32:41 GMT Raw View
In comp.std.c++ Dietmar Kuehl <dietmar_kuehl@yahoo.com> wrote:
> Hi,
> Carlos Moreno wrote:
>> While sacrificing encapsulation and all the convenience of OO
>> programming.
> Not that I'm much in favour of this idea but this is an unjustified
> criticism: There was no mention that global functions get special
> rights just because they can be called using member notation! All this
> proposal is about is to change the name lookup such that global
> functions are considered when using member notion (and, possibly, vice
> versa; I'm not clear about that one). There is nothing said which
> would grant special rights to the global functions.
Indeed, the only way a "global" function could muck around with the
internals of a class is if the "internals" were declared public, or if
the function was a friend...
-Chris
http://www.nondot.org/~sabre/Projects/CXX/NameLookup.html
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 31 May 01 17:32:04 GMT Raw View
In article <CQVQ6.7750$ki5.106354@vixen.cso.uiuc.edu>, Chris Lattner
<sabre@nondot.org> writes
>The problem is that people currently PREFER to write in the o.foo()
>form, but are sometimes REQUIRED to write in the foo(o) form. I am
>not proposing banning anything: we already have two forms. What I
>am proposing is that we unify the symantic equilivence by making
>them syntactically equilivent.
And you entirely miss the point that this causes major problems with
name lookup. Those of us who have been around these issues for the last
decade know just how fragile that area is. o.foo() and foo(o) specify
entirely different scopes for lookup and any attempt to combine them
would be a nest of vipers.
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 01 Jun 01 14:55:18 GMT Raw View
In article <e6WQ6.7754$ki5.106354@vixen.cso.uiuc.edu>, Chris Lattner
<sabre@nondot.org> writes
>In comp.std.c++ James Kanze <James.Kanze@dresdner-bank.com> wrote:
>> I very much favor the obj.fun() syntax for model objects -- the
>> function IS part of the object definition, and defines the object's
>> behavior.
>
>Exactly. The problem is the times when you are not ALLOWED to add a
>member to the class, even though it would be syntactically cleaner.
Maybe, but it also impacts on the overloading results of a name lookup
(some may think the consequence desirable, but the price will be
potential silent breakage of other code)
>
>> On the other hand, you just don't go around adding
>> additional functionality to such objects. The inability to extend the
>> functionality is a feature, not a flaw.
>
>Point taken. Then again, we are not requiring people to add stuff to
>your classes. One would assume that if they were using your classes
>they would continue to use the global functions that operate on them
>in the same way that they were intended - as global functions - even
>though they COULD be used as members...
>
>> For value objects, well, I'm pretty used to writing sqrt(x). So why
>> not substr(s,i,j), rather than s.substr(i,j)?
>
>Why not allow both?
class X {
public void algo();
...
}
algo() applies some algorithm to instances of X. Now I come along and
note that I can provide that functionality in a different way that works
better for my purposes so I write:
namespace mywork {
void algo(X &);
}
Now you come along and change the language so that my version behaves
like a member function. Now, all my already written code falls over (at
least noisily in this instance)
Scope issues are very important in a context of overloading function
names, think about it (saves me having to bore everyone with long
screeds of detail). We are not designing a new language but attempting
to refine an already widely used one.
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: 01 Jun 01 14:57:55 GMT Raw View
andrewalex@hotmail.com (Andrei Alexandrescu) wrote (abridged):
> > we can easily add global foo (even put it in the same namespace
> > for Koenig's sake) if we do not want to use "dot":
> >
> > inline void foo( MyClass& m, int i ) { m.foo( i ); }
>
> I agree. I also hope you agree that the maintenance burden for that
> minor convenience would be too big.
Are you saying it is OK for every function signature to have to be
written 4 times? It already has to be written twice, once for declaration
and once for definition. If every member function also has to have a
global declaration/definition pair, which basically repeats the member
function, isn't that terribly redundant? It seems like bad engineering to
me.
> The thing is, for a reason or another, people vastly prefer obj.Fun()
> to Fun(obj).
I'm not sure I agree. Currently the language forces us to write member
functions, because it is the only way to make them virtual and it is
easier than using "friend" everywhere.
As far as calling the function is concerned, f(o) is better precisely
because it is more generic. It is the only syntax supported when o is an
integer or built-in type. It is the syntax which enables f to be added to
a type retrospectively. So the status quo must surely prefer f(o).
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: James Kanze <James.Kanze@dresdner-bank.com>
Date: 01 Jun 01 14:58:01 GMT Raw View
Francis Glassborow wrote:
> In article <CQVQ6.7750$ki5.106354@vixen.cso.uiuc.edu>, Chris Lattner
> <sabre@nondot.org> writes
> >The problem is that people currently PREFER to write in the o.foo()
> >form, but are sometimes REQUIRED to write in the foo(o) form. I am
> >not proposing banning anything: we already have two forms. What I
> >am proposing is that we unify the symantic equilivence by making
> >them syntactically equilivent.
> And you entirely miss the point that this causes major problems with
> name lookup. Those of us who have been around these issues for the
> last decade know just how fragile that area is. o.foo() and foo(o)
> specify entirely different scopes for lookup and any attempt to
> combine them would be a nest of vipers.
True, but we already combine them in operator overloading. If I
write: a + b (where a and b are of user defined types), the compiler
is obliged to lookup and combine both TypeA::operator+( TypeB ) and
operator+( TypeA , TypeB ) (plus any operator+ in the namespaces in
which TypeA and TypeB are defined).
The nest of vipers is already present.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Chris Lattner<sabre@nondot.org>
Date: 1 Jun 2001 13:30:40 -0400 Raw View
In comp.lang.c++.moderated Dietmar Kuehl <dietmar_kuehl@yahoo.com> wrote:
> My first observation is that this is, obviously, a language change and
> being a library guy I'm used to think in terms of library mechanism to
> implement specific things: Things which can be done in the library are
> more under my control and actually a library can be used on different
> compilers.
Certainly: Standard library extensions will be an important part of the
new standard C++. Library enhancements, however, cannot accomplish
certain things in a generic way with the current C++ semantics. As
pointed out in the doc, this extension would simutanously make library
development easier as well as make the current standard library
more uniform.
> Thus, library changes are easier to implement. Languages
> changes rely on all compiler vendors to eventually catch up although
> it would probably be possible to implement this specific change in
> terms of C++-to-C++ preprocessor which resolves certain apparent
> member function calls to function calls of global functions.
Definately. On the other hand, this extension has been deliberately
selected because it requires little change to the compiler, and has a
very broad positive effect on both library users and implementers alike.
I belive that it falls under the catagory of "simplifying and unifying
the C++ language" that Bjarne Stroustrup seems to think is appropriate
for the next C++ spec...
> The next thing is that this stuff is, obiously, only necessary for
> generic implementations: A specific implementation can always use the
> "right" form, even if this results in somewhat inconsistent use.
True from an absolute standpoint. Is it really reasonable though, to
expect (especially new) programmers to figure out the wierd symantics
(that probably evolved over time as the library developed) that a
library requires? Other languages are more usable than C++ partially
because they don't draw needless distinctions like this...
Also, times change and it is often desirable to add to, extend, and
otherwise modify classes that you cannot change the definitions of...
which is hard to do on a library level. :)
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Chris Lattner<sabre@nondot.org>
Date: 1 Jun 2001 13:32:32 -0400 Raw View
In comp.lang.c++.moderated Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
>>The problem is that people currently PREFER to write in the o.foo()
>>form, but are sometimes REQUIRED to write in the foo(o) form. I am
>>not proposing banning anything: we already have two forms. What I
>>am proposing is that we unify the symantic equilivence by making
>>them syntactically equilivent.
> And you entirely miss the point that this causes major problems with
> name lookup. Those of us who have been around these issues for the last
> decade know just how fragile that area is. o.foo() and foo(o) specify
> entirely different scopes for lookup and any attempt to combine them
> would be a nest of vipers.
In the document, I propose an entirely backwards compatible way of doing this
that would be relatively safe and simple to implement: only try to match the
other form if no match can be found. Thus the name lookup rules would look
like this:
1. Try normal stuff
2. If match found, use it
3. If no match found
3a. Try using method or nonmethod syntax as appropriate, duplicating name
lookup stages from step 1.
3b. If match found, use it.
3c. If no match found, bail out.
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 1 Jun 2001 18:20:55 -0400 Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote in message
news:memo.20010531221324.46715D@brangdon.madasafish.com...
> andrewalex@hotmail.com (Andrei Alexandrescu) wrote (abridged):
> > > we can easily add global foo (even put it in the same namespace
> > > for Koenig's sake) if we do not want to use "dot":
> > >
> > > inline void foo( MyClass& m, int i ) { m.foo( i ); }
> >
> > I agree. I also hope you agree that the maintenance burden for that
> > minor convenience would be too big.
>
> Are you saying it is OK for every function signature to have to be
> written 4 times?
Hey, I said "BIG" maintenance burden.
> > The thing is, for a reason or another, people vastly prefer obj.Fun()
> > to Fun(obj).
>
> I'm not sure I agree. Currently the language forces us to write member
> functions, because it is the only way to make them virtual and it is
> easier than using "friend" everywhere.
>
> As far as calling the function is concerned, f(o) is better precisely
> because it is more generic. It is the only syntax supported when o is an
> integer or built-in type. It is the syntax which enables f to be added to
> a type retrospectively. So the status quo must surely prefer f(o).
I didn't notice the same among programmers :o(. Most see the member
functions syntax as a sacrosanct emanation of the OOP Force...
Andrei
--
Check out THE C++ Seminar: 3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 29 May 2001 23:47:22 -0400 Raw View
"James Kanze" <James.Kanze@dresdner-bank.com> wrote in message
news:3B11FF54.FC105B01@dresdner-bank.com...
> I think that part of the problem is that people try too much to make
> one size fit all. In practice, I find that I have two large types of
> classes: user defined values and model objects. These classes have
> radically different uses -- it is very rare for a model object to
> support assignment, for example, and user defined values don't use
> inheritance, at least not in the OO isA way.
Makes sense.
> I very much favor the obj.fun() syntax for model objects -- the
> function IS part of the object definition, and defines the object's
> behavior.
Huh? What about functions that involve multiple polymorphic objects?
> On the other hand, you just don't go around adding
> additional functionality to such objects. The inability to extend the
> functionality is a feature, not a flaw.
You *always* want to add higher-level functionality in terms of a basic
interface. It's a definite flaw, a flaw that works against encapsulation and
in favor of inheritance abuse.
Andrei
--
Check out THE C++ Seminar: 3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Chris Lattner<sabre@nondot.org>
Date: 30 May 2001 14:03:23 -0400 Raw View
In comp.std.c++ James Kanze <James.Kanze@dresdner-bank.com> wrote:
> I very much favor the obj.fun() syntax for model objects -- the
> function IS part of the object definition, and defines the object's
> behavior.
Exactly. The problem is the times when you are not ALLOWED to add a
member to the class, even though it would be syntactically cleaner.
> On the other hand, you just don't go around adding
> additional functionality to such objects. The inability to extend the
> functionality is a feature, not a flaw.
Point taken. Then again, we are not requiring people to add stuff to
your classes. One would assume that if they were using your classes
they would continue to use the global functions that operate on them
in the same way that they were intended - as global functions - even
though they COULD be used as members...
> For value objects, well, I'm pretty used to writing sqrt(x). So why
> not substr(s,i,j), rather than s.substr(i,j)?
Why not allow both?
-Chris
http://www.nondot.org/~sabre/Projects/CXX/NameLookup.html
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Chris Lattner<sabre@nondot.org>
Date: 30 May 2001 14:04:46 -0400 Raw View
In comp.std.c++ James Kanze <James.Kanze@dresdner-bank.com> wrote:
> Dietmar Kuehl wrote:
>> Carlos Moreno wrote:
>> All
>> this proposal is about is to change the name lookup such that global
>> functions are considered when using member notion (and, possibly,
>> vice versa; I'm not clear about that one). There is nothing said
>> which would grant special rights to the global functions.
> I thought (but I could be wrong) that it was the reverse that was
> proposed; that member functions could be written using global function
> syntax, with the base object as the first parameter.
The proposal would allow both, because both are functionally identical.
> Personally, I wouldn't use this if it were available. I don't like
> the idea that a.f(b,c) and f(a,b,c) call exactly the same function;
> overloading is confusing enough as is. And I share Francis'
> hesitations about touching anything that involves name lookup.
For most cases though, the available overloads would not be ambiguous.
If the choice of overloads was ambiguous, the compiler would either
choose the "best" one, or choke on the ambiguity. This is how C++
already operates.
If you look at this from a different perspective, this is exactly how
namespaces already operate. Thus classes are simply namespaces that
contain data and can be instantiated. Perhaps it should be possible
to make a function "namespace private", that is visible only to
functions in the current namespace... But that is fuel for a different
discussion _NOT_ related to this one. :)
> There are some legitimate arguments (from Scott Meyer, among others)
> that all function calls should have the form f(a,b,c). I can
> sympathize with them, although I personally like the current syntax.
> However, I think it's too late to change now. We can't ban the
> current form, and having two forms would probably lead to too much
> confusion.
The problem is that people currently PREFER to write in the o.foo()
form, but are sometimes REQUIRED to write in the foo(o) form. I am
not proposing banning anything: we already have two forms. What I
am proposing is that we unify the symantic equilivence by making
them syntactically equilivent.
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 27 May 2001 09:15:31 -0400 Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message
news:7f2735a5.0105241250.3e6e4825@posting.google.com...
> Your paper does include this statement:
> This proposal only applies to non-virtual methods that do
> not require more than public access to the class data.
> (You forgot to mention the qualifier "public" as well.) However,
> most OOP programmers consider it bad form to make any class
> data public; for them, this statement simplifies to "public
> non-virtual methods implemented in terms of other public methods".
> I suspect that this is not a high percentage of member functions
> today.
But that's wrong. Take any container in the standard library, and you'll be
surprised how much functionality can be implemented by calling into a small
core.
Many member functions today don't need access to private data and are there
only for the sake of the convenience of the dot notation. Making the dot
notation affordable for those extending a class would have big benefits in
terms of encapsulation.
> Every well-considered proposal has a motivator, and this is where
> you expose your motivation. You wish to extend a class without modifying
> a class definition; in fact, you consider this to be a weakness of C++.
>
> I don't. Encapsulation means more than just private data members. If
> function foo() is to become part of the public interface for the class,
> then it should not be easy to add it in a way that might break other
> code. There are alternatives.
But according to language rules any function that takes an argument of type
A (be it through reference or const-reference) *is* part of A's interface
already. See operators and Herb's explanation of Koenig lookup, mentioned
elsewhere in this thread.
The view that the interface of a class must be fixed by the class designer
is plain wrong. Different class users have different complex needs from that
class. Consider a matrix class. Some need matrix inversion, Jordanization,
and all those things in matrix algebra I forgot a long time ago; some others
just need to sum the columns. Why lump it all in one matrix uberclass?
As I demonstrated, the basic_string class needs to have only 75-20 lines of
code accessing the private implementation, while the rest (over 700 lines of
code) can be implemented in terms of the core of primitives.
Less member functions means better encapsulation. It also means better
designs, because class designers will focus on minimalism - core functions
that would allow efficient interaction with the concept underlied by that
class - rather than concentrating on fluffy convenience functions which have
unnecessary and dangerously close access to the internals.
> In C++, there are two ways to "extend" a class. One way is through
> derivation; you can create a new class derived from the first one and
> add as many member functions as you like without making any
> modifications to the base class.
Blech.
> The other way is to modify the class definition itself.
Ditto.
> But my point here is that if a function is considered to be part of the
> way that a class works, then it SHOULD be difficult to add it to the
> interface of the class.
Then you should hate C++. Nonmember functions /are/ part of the way a class
works *today*.
> class CustomerWithFoo : public Customer {
> void foo(int a, double b, string c)
> { ::foo(*this, a, b, c); }
> };
> // From here on, use CustomerWithFoo instead of just Customer
> int main() {
> CustomerWithFoo f;
> f.foo(1, 2.3, "Yes");
> }
>
> This extends class Customer by adding function foo, without having to
> make any changes to class Customer. On the other hand, it does not
> affect any code that uses Customer directly, such as the group that
> wrote class Customer in the first place.
Perhaps using inheritance just to add convenience member functions is the
worst, most gruesome, form of abuse of inheritance.
Andrei
--
Check out THE C++ Seminar: 3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: James Kanze <James.Kanze@dresdner-bank.com>
Date: 28 May 01 16:05:04 GMT Raw View
Andrei Alexandrescu wrote:
> The thing is, for a reason or another, people vastly prefer
> obj.Fun() to Fun(obj). It's one of those little inconsequential
> things that people just like. Then, they don't like that for some
> functions (the ones that the implementer initially provided) they
> can happily write obj.Fun() while for supplemental functions added
> by others, they must use Fun(obj). Boooo! They just hate it.
I think that part of the problem is that people try too much to make
one size fit all. In practice, I find that I have two large types of
classes: user defined values and model objects. These classes have
radically different uses -- it is very rare for a model object to
support assignment, for example, and user defined values don't use
inheritance, at least not in the OO isA way.
I very much favor the obj.fun() syntax for model objects -- the
function IS part of the object definition, and defines the object's
behavior. On the other hand, you just don't go around adding
additional functionality to such objects. The inability to extend the
functionality is a feature, not a flaw.
For value objects, well, I'm pretty used to writing sqrt(x). So why
not substr(s,i,j), rather than s.substr(i,j)?
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: allan_w@my-dejanews.com (Allan W)
Date: 25 May 01 03:40:14 GMT Raw View
sabre@nondot.org wrote in message news:<DZ3N6.6492$ki5.89991@vixen.cso.uiuc.edu>...
> This is a quick writeup I did for an idea that I would really like
> added to C++'0x (I haven't seen it mentioned before):
>
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
Your paper is quite interesting; you present your opinions quite
clearly, and you make a lot of sense. However, IMHO, I believe
that you have an unstated premise wrong.
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
This demonstrates your unstated premise quite clearly -- that the
primary reason to use member functions is notational convenience.
In fact, I believe that quite the opposite is true -- when it was
first introduced, it looked very, very strange to people familiar with
C. However, the notation selected was a very natural extension of the
syntax for member data elements, so soon it became quite natural.
Your paper does include this statement:
This proposal only applies to non-virtual methods that do
not require more than public access to the class data.
(You forgot to mention the qualifier "public" as well.) However,
most OOP programmers consider it bad form to make any class
data public; for them, this statement simplifies to "public
non-virtual methods implemented in terms of other public methods".
I suspect that this is not a high percentage of member functions
today.
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition)
Every well-considered proposal has a motivator, and this is where
you expose your motivation. You wish to extend a class without modifying
a class definition; in fact, you consider this to be a weakness of C++.
I don't. Encapsulation means more than just private data members. If
function foo() is to become part of the public interface for the class,
then it should not be easy to add it in a way that might break other
code. There are alternatives.
In C++, there are two ways to "extend" a class. One way is through
derivation; you can create a new class derived from the first one and
add as many member functions as you like without making any
modifications to the base class.
The other way is to modify the class definition itself. This may well
be the right thing to do, but not without careful consideration --
it is inherently dangerous. The problem used to be much worse than it
is today, though -- C++ encourages (but does not demand!) the use of
"encapsulation" to help reduce these problems.
Usually, short descriptions of encapsulation go something like this:
Prevent code outside the class from accessing private data members.
That way, if the data members change definition, only code within
the class must change to match; so long as the interface is kept
upward-compatible, there is no need to change any code outside the
class.
That's true, but it omits far too much. Here is my version:
Prevent code outside the class from doing ANYTHING with the class
except to access the public interface, and design the interface to
minimize (as much as possible) dependance on specific data elements.
That way, even if there are radical changes to the class, most of
the clients will be able to use it with no source code changes.
I'm resisting the urge to start giving out rules of class design here.
But my point here is that if a function is considered to be part of the
way that a class works, then it SHOULD be difficult to add it to the
interface of the class.
> while imposing little extra work
> on compiler implementors, and costing no runtime performance. It also
> helps address the sort(list) vs list.sort() issue, in a very different
> way from previous posts.
I'm not sure how much work it is for implementors. Usually this isn't a
huge concern anyway; we strive to make sure that implementors CAN do it,
but we don't worry if it's a big change or a little one, from their
perspective.
But how much work is this for you?
class CustomerWithFoo : public Customer {
void foo(int a, double b, string c)
{ ::foo(*this, a, b, c); }
};
// From here on, use CustomerWithFoo instead of just Customer
int main() {
CustomerWithFoo f;
f.foo(1, 2.3, "Yes");
}
This extends class Customer by adding function foo, without having to
make any changes to class Customer. On the other hand, it does not
affect any code that uses Customer directly, such as the group that
wrote class Customer in the first place.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 24 May 2001 16:13:49 -0400 Raw View
"Matvei Brodski" <mbrodski@bear.com> wrote in message
> Wait, let's go back. The proposal gives you a chance to use "dot" notation
> where you can not do it now - nothing more. The other way around is a
given:
>
> class MyClass {
> public:
> void foo( int );
> };
>
> we can easily add global foo (even put it in the same namespace
> for Koenig's sake) if we do not want to use "dot":
>
> inline void foo( MyClass& m, int i ) { m.foo( i ); }
I agree. I also hope you agree that the maintenance burden for that minor
convenience would be too big.
> So, this is not a problem the Chris's proposal solves. Chris sees the
problem
> in that we can not do the opposite. So, if we can define global bar:
>
> void bar( MyClass& m );
>
> Chris wants (for some reason) to be able to call it like member:
>
> m.bar();
>
> Now, before we decide that we must have this, we need to prove it to
> ourselves that we really need it. Especially given that "convinience"
> of the dot notation is (as it is) already strongly doubted by certain very
> respected people (some even called it "chymera").
>
> Can you give me an example where you would really suffer because you
> can not use dot notation? Some real problem that that dot would solve?
The thing is, for a reason or another, people vastly prefer obj.Fun() to
Fun(obj). It's one of those little inconsequential things that people just
like. Then, they don't like that for some functions (the ones that the
implementer initially provided) they can happily write obj.Fun() while for
supplemental functions added by others, they must use Fun(obj). Boooo! They
just hate it.
Another thing is that generic algorithms have a harder time dealing with two
separate syntaxes.
Andrei
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Heinz Huber <hhuber@racon-linz.at>
Date: 24 May 2001 16:14:12 -0400 Raw View
Matvei Brodski wrote:
>
> "Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in message news:<9e8t2l$1jvpb$1@ID-14036.news.dfncis.de>...
> > "Carlos Moreno" <moreno@mochima.com> wrote in message
> > news:3B05EAF5.84C03F19@mochima.com...
> > > sabre@nondot.org wrote:
> > > > Basically, it proposes making these two forms equivalent for invoking
> > > > a method:
> > > >
> > > > a.foo(b, c, d);
> > > > foo(a, b, c, d);
> > > >
> > > > Which addresses several weaknesses of C++
> > >
> [snip]
> > The "convenience" of OO programming, if you refer to the dot notation, is a
> > chymera.
> >
> > > > (f.e. you can't extend a class
> > > > without modifying the class definition)
> > >
> > > You can extend it -- provided that you use exclusively use the available
> > > public interface.
> >
> > Which is way cool! Here's the increase in encapsulation I was talking about.
>
> Wait, let's go back. The proposal gives you a chance to use "dot" notation
> where you can not do it now - nothing more. The other way around is a given:
>
> class MyClass {
> public:
> void foo( int );
> };
>
> we can easily add global foo (even put it in the same namespace
> for Koenig's sake) if we do not want to use "dot":
>
> inline void foo( MyClass& m, int i ) { m.foo( i ); }
>
> So, this is not a problem the Chris's proposal solves.
And in one of the other threads on the future, there was a proposal concerning
variable type lists for templates. If this principle would be accepted, you
could write the above as a generic template for every function you want to use
that way:
template <class T, var> function(T &object, var) { object.function(var); }
The meaning and use of the var part is still to be defined.
[snipped opposite (call global foo as m.foo)]
Heinz
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: 24 May 01 05:15:45 GMT Raw View
sabre@nondot.org wrote:
>
> This is a quick writeup I did for an idea that I would really like
> added to C++'0x (I haven't seen it mentioned before):
>
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
>
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition) while imposing little extra work
> on compiler implementors, and costing no runtime performance. It also
> helps address the sort(list) vs list.sort() issue, in a very different
> way from previous posts.
>
> I can't wait to be shot down. ;)
Half of it (the more important half, IMHO) could be done with simple
forwarder functions:
void foo(A& a, X b, Y c, Z d)
{
a.foo(b, c, d);
}
For some functions, templates would be useful (which then could
even have special versions for special cases):
template<class Container>
typename Container::iterator begin(Container& c)
{
return c.begin();
}
template<class Container>
typename Container::iterator end(Container& c)
{
return c.end();
}
template<class T, std::size_t size>
T* begin(T (&arr)[size])
{
return arr;
}
template<class T, std::size_t size>
T* end(T (&arr)[size])
{
return arr+size;
}
This would allow both
std::vector<int> v;
std::for_each(begin(v), end(v), foo);
and
int a[20];
std::for_each(begin(a), end(a), foo);
I don't mind that you cannot write
std::for_each(a.begin(), a.end(), foo);
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Bing Swen" <bswen@icl.pku.edu.cn>
Date: 24 May 01 05:19:54 GMT Raw View
<sabre@nondot.org> wrote in message
news:DZ3N6.6492$ki5.89991@vixen.cso.uiuc.edu...
> This is a quick writeup I did for an idea that I would really like
> added to C++'0x (I haven't seen it mentioned before):
>
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
>
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition) while imposing little extra work
> on compiler implementors, and costing no runtime performance. It also
> helps address the sort(list) vs list.sort() issue, in a very different
> way from previous posts.
>
> I can't wait to be shot down. ;)
>
> -Chris
>
Interesting at first glance. But actually nothing but a plain
syntax sugar. No substantial help indeed. The substantial thing
about a "member function" is dynamic binding -- dispatching via
vtable. And C++ has fix-sized vtables.
Making what belongs to a member a member makes, IMO, everything
predictable and our lives easier. Why produce problems instead
of solving really problems?
Regards,
-bs-
----
CS Dept., Peking University
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Simon Withers - CSCI/F1999 <swithers@scs.ryerson.ca>
Date: 24 May 2001 14:44:56 -0400 Raw View
On 22 May 2001, Robert O'Dowd wrote:
> sabre@nondot.org wrote:
> >
> > This is a quick writeup I did for an idea that I would really like
> > added to C++'0x (I haven't seen it mentioned before):
> >
> > http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
> >
> > Basically, it proposes making these two forms equivalent for invoking
> > a method:
> >
> > a.foo(b, c, d);
> > foo(a, b, c, d);
> >
> > Which addresses several weaknesses of C++ (f.e. you can't extend a class
> > without modifying the class definition) while imposing little extra work
> > on compiler implementors, and costing no runtime performance. It also
> > helps address the sort(list) vs list.sort() issue, in a very different
> > way from previous posts.
> >
>
> A few quick comments, in no particular order ...
>
> 1) It is possible to have...
>
> class A
> {
> public:
> foo(int b, int c, int d);
> };
>
> void foo(A &a, int b, int c, int d)
> {
> a.foo(b,c,d);
> }
>
> which allows one to explicitly achieve what you're after.
>
> 2) Allowing equivalence of a.foo(...) and foo(a, ...) gives problems
> of name lookup, which [as Francis mentioned in this thread already]
> is one of the more fragile parts of C++. The thought of breaking
> that, and potential impact on existing code, is not exactly something
> that will thrill people.
I'm not sure that this proposal needs to break name lookup at all.
Here's my idea...
By the time a compiler sees a call such as a.foo(b,c,d) the compiler needs
to have seen the definition of a.foo() and so should know if a.foo() is
virtual or not, so...
When the compiler sees a class definition such as
class A
{
public:
foo(int b, int c, int d);
};
could it not rewrite the function into the enclosing namespace as:
void foo(A &a, int b, int c, int d);
and then whenever it encounters a member function call for a non-virtual
function, translated it from the a.foo(b,c,d) form to the
foo(a,b,c,d) form.
> 3) What would happen (in this proposed scheme) if I provided this?
>
> void Something(A &a, double x);
>
> Would this function be able to access the private/protected members
> of class A? If so, we are subverting the access control provided
> by the class declaration. That is open to abuse, both accidental
> and intentional. The flip side is that, unless this function can
> obtain access to private/protected members, it achieves nothing
> different from the approach I suggested above: it will still have
> to use public class members unless it it declared as a friend.
If you want Something() to have access to A's privates, you need to make
Something into a friend. For functions which the compiler silently
converts as I suggest above, the compiler should insert a friendship
statement.
Simon Withers
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Carlos Moreno <moreno@mochima.com>
Date: 22 May 01 20:54:23 GMT Raw View
Andrei Alexandrescu wrote:
>
> > > Basically, it proposes making these two forms equivalent for invoking
> > > a method:
> > >
> > > a.foo(b, c, d);
> > > foo(a, b, c, d);
> > >
> > > Which addresses several weaknesses of C++
> >
> > While sacrificing encapsulation and all the convenience of OO
> > programming.
>
> I'm sure there is a confusion around here.
There was :-) After reading Dietmar's reply, I saw where my
confusion was.
> The "convenience" of OO programming, if you refer to the dot notation
Of course not! I just drew extra conclusions from the original
message -- thinking that he was proposing that you can extend the
class as if you were adding methods with full access to private
members.
Now that I understand his idea, I kind of like it... Not that I
would defend it with my life... :-)
Cheers,
Carlos
--
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: mbrodski@bear.com (Matvei Brodski)
Date: 22 May 01 20:54:56 GMT Raw View
"Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in message news:<9e8t2l$1jvpb$1@ID-14036.news.dfncis.de>...
> "Carlos Moreno" <moreno@mochima.com> wrote in message
> news:3B05EAF5.84C03F19@mochima.com...
> > sabre@nondot.org wrote:
> > > Basically, it proposes making these two forms equivalent for invoking
> > > a method:
> > >
> > > a.foo(b, c, d);
> > > foo(a, b, c, d);
> > >
> > > Which addresses several weaknesses of C++
> >
[snip]
> The "convenience" of OO programming, if you refer to the dot notation, is a
> chymera.
>
> > > (f.e. you can't extend a class
> > > without modifying the class definition)
> >
> > You can extend it -- provided that you use exclusively use the available
> > public interface.
>
> Which is way cool! Here's the increase in encapsulation I was talking about.
Wait, let's go back. The proposal gives you a chance to use "dot" notation
where you can not do it now - nothing more. The other way around is a given:
class MyClass {
public:
void foo( int );
};
we can easily add global foo (even put it in the same namespace
for Koenig's sake) if we do not want to use "dot":
inline void foo( MyClass& m, int i ) { m.foo( i ); }
So, this is not a problem the Chris's proposal solves. Chris sees the problem
in that we can not do the opposite. So, if we can define global bar:
void bar( MyClass& m );
Chris wants (for some reason) to be able to call it like member:
m.bar();
Now, before we decide that we must have this, we need to prove it to
ourselves that we really need it. Especially given that "convinience"
of the dot notation is (as it is) already strongly doubted by certain very
respected people (some even called it "chymera").
Can you give me an example where you would really suffer because you
can not use dot notation? Some real problem that that dot would solve?
Personally, I do agree with "dot is chymera". Functions that can be
described as "operations defined on the given type" (rather, then
"features (attributes) of the type") should be made global
(and, thanks to Sutter's Interface Principle, still be considered
part of class interface). Say, consider class complex:
While real and imaginary parts are clearly attributes of a complex
number, "sin" is not. sin is a function (as in "mapping") defined on
complex numbers which looks much more natural when called as:
complex z1 = sin( z2 );
then as:
complex z1 = z2.sin();
Matvei.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Robert O'Dowd" <nospam@nonexistant.com>
Date: 22 May 01 20:55:21 GMT Raw View
sabre@nondot.org wrote:
>
> This is a quick writeup I did for an idea that I would really like
> added to C++'0x (I haven't seen it mentioned before):
>
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
>
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition) while imposing little extra work
> on compiler implementors, and costing no runtime performance. It also
> helps address the sort(list) vs list.sort() issue, in a very different
> way from previous posts.
>
A few quick comments, in no particular order ...
1) It is possible to have...
class A
{
public:
foo(int b, int c, int d);
};
void foo(A &a, int b, int c, int d)
{
a.foo(b,c,d);
}
which allows one to explicitly achieve what you're after.
2) Allowing equivalence of a.foo(...) and foo(a, ...) gives problems
of name lookup, which [as Francis mentioned in this thread already]
is one of the more fragile parts of C++. The thought of breaking
that, and potential impact on existing code, is not exactly something
that will thrill people.
3) What would happen (in this proposed scheme) if I provided this?
void Something(A &a, double x);
Would this function be able to access the private/protected members
of class A? If so, we are subverting the access control provided
by the class declaration. That is open to abuse, both accidental
and intentional. The flip side is that, unless this function can
obtain access to private/protected members, it achieves nothing
different from the approach I suggested above: it will still have
to use public class members unless it it declared as a friend.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: 20 May 01 12:45:03 GMT Raw View
In article <DZ3N6.6492$ki5.89991@vixen.cso.uiuc.edu>, sabre@nondot.org
writes
>This is a quick writeup I did for an idea that I would really like
>added to C++'0x (I haven't seen it mentioned before):
>
>http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>
>Basically, it proposes making these two forms equivalent for invoking
>a method:
>
>a.foo(b, c, d);
>foo(a, b, c, d);
>
>Which addresses several weaknesses of C++ (f.e. you can't extend a class
>without modifying the class definition) while imposing little extra work
>on compiler implementors, and costing no runtime performance. It also
>helps address the sort(list) vs list.sort() issue, in a very different
>way from previous posts.
>
>I can't wait to be shot down. ;)
I suspect that the problem is that this touches on one of the most
fragile parts of C++: name lookup. Many of us shudder when we have to
look yet again at those rules because experience tells us we are about
to break something:(
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Carlos Moreno <moreno@mochima.com>
Date: 20 May 01 12:45:52 GMT Raw View
sabre@nondot.org wrote:
>
> This is a quick writeup I did for an idea that I would really like
> added to C++'0x (I haven't seen it mentioned before):
>
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
>
> Which addresses several weaknesses of C++
While sacrificing encapsulation and all the convenience of OO
programming.
> (f.e. you can't extend a class
> without modifying the class definition)
You can extend it -- provided that you use exclusively use the available
public interface. If what you're proposing is that outsiders of the
class be allowed to define functions like the above and access the
internals of the class, then you might as well propose that the
keyword private and the notion of data hiding be removed altogether...
> helps address the sort(list) vs list.sort() issue, in a very different
> way from previous posts.
But only that one -- not sort(vector) vs. sort(vector.begin(),
vector.end())
> I can't wait to be shot down. ;)
Well, this was my attempt at it ;-)
Carlos
--
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 20 May 01 12:57:25 GMT Raw View
sabre@nondot.org wrote:
...
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition) while imposing little extra work
That's eather false, or not a weakness, depending upon what you mean. In
one sense, it's perfectly possible to extend a class definition - the
process is called inheritance.
Not being able to extend a class definition except by inheritance is a
strength, not a weakness, because it improves the predictability of a
design. After reading a class definition from beginning to end, a C++
designer knows precisely what the members of a class are, and that
there's nothing a user can do (modulo Murphy vs. Machiavelli, of course)
to add members that would change the behavior of the code. By careful
use of access restrictions, a developer can guarantee that the parts of
a class that need to work in a particular way are hidden from outside
interference, while providing all the external handles needed to make
the class extensible through inheritance.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Dietmar Kuehl <dietmar_kuehl@yahoo.com>
Date: 20 May 01 13:30:26 GMT Raw View
Hi,
sabre@nondot.org wrote:
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
My first observation is that this is, obviously, a language change and
being a library guy I'm used to think in terms of library mechanism to
implement specific things: Things which can be done in the library are
more under my control and actually a library can be used on different
compilers. Thus, library changes are easier to implement. Languages
changes rely on all compiler vendors to eventually catch up although
it would probably be possible to implement this specific change in
terms of C++-to-C++ preprocessor which resolves certain apparent
member function calls to function calls of global functions.
The next thing is that this stuff is, obiously, only necessary for
generic implementations: A specific implementation can always use the
"right" form, even if this results in somewhat inconsistent use. As a
result, this approach is somewhat trying to fix a library problem with
a language change: The generic implementations should *only* rely on
non-member functions in the first place! This would have the whole
problem just go away, without any language change (BTW, when I'm
saying "language change" I'm referring to a compiler ie. a Core
change; technically, the library is also part of the language but I'm
considering library changes to be something different).
My personal viewpoint is that I don't think that such a language
change is really necessary. What is, however, necessary is a more
consistent library, that is, fixing what is broken rather than curing
the effects.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Dietmar Kuehl <dietmar_kuehl@yahoo.com>
Date: 20 May 2001 11:50:59 -0400 Raw View
Hi,
Carlos Moreno wrote:
> While sacrificing encapsulation and all the convenience of OO
> programming.
Not that I'm much in favour of this idea but this is an unjustified
criticism: There was no mention that global functions get special
rights just because they can be called using member notation! All this
proposal is about is to change the name lookup such that global
functions are considered when using member notion (and, possibly, vice
versa; I'm not clear about that one). There is nothing said which
would grant special rights to the global functions.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.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.research.att.com/~austern/csc/faq.html ]
Author: Chris Lattner<sabre@nondot.org>
Date: 20 May 2001 11:51:25 -0400 Raw View
> Chris Lattner wrote:
>> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>> Basically, it proposes making these two forms equivalent for invoking
>> a method:
>> a.foo(b, c, d);
>> foo(a, b, c, d);
> I actually think it's a good idea. I've been thinking along similar lines a
> bit recently too. To me at least it seems to have some parallels with Koenig
> lookup and also with the "interface principle" Herb Sutter talked about at
> the recent ACCU conference (although I wouldn't want to put words into his
> mouth).
Yup, exactly. For readers who aren't familiar with it, this article explains
it well:
http://www.gotw.ca/publications/mill02.htm
> Another advantage of this is that, except for virtual functions, member
> function pointers and non-member function pointers become compatible
> (provided the rest of the signatures are compatible). Member function
> pointers are currently IMHO syntactic and efficiency nightmares yet they're
> important for callbacks/events - the kind of thing Borland C++ Builder uses
> the non-standard __closure extension for.
Great point! I added this to the page...
> The disadvantages to the scheme I can see:
> 1. You point this out yourself in passing - references are sometimes *but
> not always* implemented as pointers. I would be happier if the first
> parameter in a "member-compatible global" function always had to be a
> pointer. Don't allow references there.
Good point. I think a reasonable implementation of this would be to
only allow global functions that take an object *pointer* as the first
argument. I suppose that is more of the kind of detail that a standards
body would hash out. :)
> 2. Currently implementers are free to implement a special calling convention
> for member functions.
Of course...
> MS call theirs thiscall. This affects your plans for
> binary compatibility between the two kinds of function call and
> interoperability of the two different styles of definition and declaration
Not really. You could consider C++'0x as a "different" language. Because it
is different, they may choose to make calling convensions identical in the
'0x version, but different in the '99 version. Obviously, backwards
compatibility (and social issues) do come into play here though. If the
C++'0x standard dictated that the pointers/calling conventions would have to
be identical, then I would assume that Microsoft(and whoever else is affected)
would change. I see that as more of an implementation issue.
> i.e.
> struct A { void mem_fn(int); }; // Uses thiscall
> void global_fn(A, int); // Doesn't use thiscall.
> void mem_fn(A, int) {} // Wrong: calling convention mismatch.
> void A::global_fn(int) {} // ditto
> I wasn't sure if you were suggesting this should work or not. If you
> continue to allow thiscall, it never will (portably).
I would probably NOT advocate this. If you declared a function in a class,
you would have to implement it as a class member. Just the invocation rules
would be modified, not the declaration rules as shown here.
> thiscall also destroys my idea of compatibility of function pointers.
> I would be interested to know what the point of thiscall is really - MS use
> it to place the this pointer in a register rather than on the stack but this
> makes it slower than their generally useable __fastcall.
Really, I don't see how thiscall would be different than fastcall. The
general point is the same: pass stuff in registers if you can. I don't see
how "this" is any different for a member function...
> AFAIK thiscall
> could be phased out without too much pain, although if any compiler vendors
> that are big on binary compatibility between releases (Sun?) actually use it
> that could be a different story.
Understood. Compilers do break binary compatibility when they have to,
however, and in this case, I would assume it to be reasonable. I disturbs
me to know that Microsoft would do something so (apparently) gratuitous
as "thiscall" which doesn't seem to give them anything for the implementation
trouble they had to go through.
> 3. As you mention, it requires some changes to the existing function name
> lookup rules. This is a very tricky area, and "The Design & Evolution of
> C++" tells how long and hard the creators of C++ tried to get it right. But
> there are other problems with the existing rules [1] so I guess these may be
> up for review even without your proposal.
As I mentioned in the intro, IANALL. As a student, I don't even have a
copy of the standard (yet). I would definately let people more familiar with
these issues make the real decisions. :)
> 4. It builds bridges across namespaces even more than Koenig lookup, because
> now global functions effectively become members of up to two namespaces -
> the one they are defined in and the one to which their first parameter
> belongs. I *think* this is a good thing, but I'm not totally sure.
I too believe that it is a good thing, and is symmetric with the rest of
C++, and particularly Koenig lookup. If it turned out not to be as simple
as I believe, then the standards body could always choose to only allow
"non member class extension" while in the same namespace. Because namespaces
can be extended at will (as this proposal does to classes), it's not a big
deal...
> But overall I like it.
Great! Thanks, I included your feedback on my web page:
http://www.nondot.org/~sabre/Projects/CXX/NameLookup.html#f1
> Notes:
> 1. For example, member functions hiding the correct Koenig lookup accessible
> function if they share the same name, one of the "swap problems". Thanks to
> Alan Griffiths for explaining this in ACCU's Overload magazine issue 41.
I think the problem there is that Koenig lookup provides more room for
ambiguity (as this proposal might). C++ chooses to error out on ambiguity
rather than make a guess, simply because it doesn't want "suprise"
behaviour later in the development cycle. I believe this to be a very
very very good thing. ;) With nonlocal class extension, however, there are
some very simple rules that you could implement to put things on a priority
scale, so that things are well defined and not ambiguous...
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: 20 May 2001 11:55:38 -0400 Raw View
glancaster@ntlworld.com (glancaster) wrote (abridged):
> > http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
I like this proposal.
> 2. Currently implementers are free to implement a special calling
> convention for member functions. MS call theirs thiscall. This
> affects your plans for binary compatibility between the two kinds
> of function call and interoperability of the two different styles
> of definition and declaration, ie
>
> struct A
> {
> void mem_fn(int); // Uses thiscall
> };
>
> void global_fn(A, int); // Doesn't use thiscall.
>
> void mem_fn(A, int) {} // Wrong: calling convention mismatch.
> void A::global_fn(int) {} // ditto
Hmmm. The proposal talks about declaration but doesn't actually say much
about definition. I suggest we require the definitions to match the
declarations. Thus the functions in your example would need to be defined
as:
void A::mem_fn(int) {}
void global_fn(A,int) {}
Clearly, only functions declared and implemented as members would have
access to private data. We are not changing anything there. We are only
changing *invocation*.
The point is that *clients* become insulated from how the function is
declared/defined:
void demo() {
A a;
a.mem_fn( 1 ); // OK.
a.global_fn( 1 ); // OK.
mem_fn( a, 1 ); // OK.
global_fn( a, 1 ); // OK.
}
In each case the compiler can generate the right calling convention.
Basically the compiler generates the same code for:
mem_fn( a, 1 );
a.global_fn( 1 );
as for:
a.mem_fn( 1 );
global_fn( a, 1 );
It is a mechanical, compile-time, source-code to source-code translation.
This means that binary compatibility is not an issue. Switching from a
member to a non-member will mean a recompile under the "One definition"
rule. A vendor might choose not to require that recompile, which would
enable library compatibility between releases, but this is a "quality of
implementation" issue. The standard shouldn't require it.
> 1. You point this out yourself in passing - references are sometimes
> *but not always* implemented as pointers. I would be happier if
> the first parameter in a "member-compatible global" function always
> had to be a pointer. Don't allow references there.
As I write above, I don't think binary compatibility is a problem. I
distrust pointer/reference ambiguity but I would be inclined to support
references, not pointers. This matches the current rule with member
operators. Eg:
void demo() {
A a;
A &ra = a;
A *pa = &a;
mem_fn( a, 1 ); // OK.
mem_fn( ra, 1 ); // OK.
mem_fn( *pa, 1 ); // OK.
//mem_fn( pa, 1 ); // Not OK.
a.global_fn( 1 ); // OK.
ra.global_fn( 1 ); // OK.
pa->global_fn( 1 ); // OK.
//pa.global_fn( 1 ); // Not OK.
}
Pointers must be dereferenced explicitly, either with * or ->.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: Chris Lattner<sabre@nondot.org>
Date: 20 May 2001 12:06:12 -0400 Raw View
In comp.lang.c++.moderated Mike Smith <smithmc@dontspamonmemichaelsmith.org> wrote:
>> Which addresses several weaknesses of C++ (f.e. you can't extend a class
>> without modifying the class definition) while imposing little extra work
> That may not be universally considered a weakness...
It is certainly a weakness if you _cannot_ change the class definition:
for example the class resides in a system library, a 3rd party library, or
is part of frozen code that you are not allowed to change.
Also, while it may not be such a big deal for 10K line projects... when you
get to 100K you would probably start to appreciate such a facility...
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 21 May 01 03:35:30 GMT Raw View
Chris Lattner wrote:
>
> In comp.lang.c++.moderated Mike Smith <smithmc@dontspamonmemichaelsmith.org>
wrote:
> >> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> >> without modifying the class definition) while imposing little extra work
>
> > That may not be universally considered a weakness...
>
> It is certainly a weakness if you _cannot_ change the class definition:
> for example the class resides in a system library, a 3rd party library, or
> is part of frozen code that you are not allowed to change.
Why is that a weakness? It's precisely in such a situation that I'm glad
to be able to ensure the integrity of the class definition.
> Also, while it may not be such a big deal for 10K line projects... when you
> get to 100K you would probably start to appreciate such a facility...
No, I'd begin to have a greater appreciation for the lack of such a
facility. If you could reopen the class definition, you could radically
change the behavior of code written by the original designer, in ways
that designer never anticipated. By closing the class definition, and
allowing extensions to a class only through inheritance or containment,
C++ is a far safer programming environment then it would be if class
definitions could be re-opened.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 21 May 2001 06:27:27 -0400 Raw View
"Carlos Moreno" <moreno@mochima.com> wrote in message
news:3B05EAF5.84C03F19@mochima.com...
> sabre@nondot.org wrote:
> > Basically, it proposes making these two forms equivalent for invoking
> > a method:
> >
> > a.foo(b, c, d);
> > foo(a, b, c, d);
> >
> > Which addresses several weaknesses of C++
>
> While sacrificing encapsulation and all the convenience of OO
> programming.
I'm sure there is a confusion around here. Did you read the web page? The
proposal, if ever approved, would greatly *increase* programmer's ability to
encapsulate.
The "convenience" of OO programming, if you refer to the dot notation, is a
chymera.
> > (f.e. you can't extend a class
> > without modifying the class definition)
>
> You can extend it -- provided that you use exclusively use the available
> public interface.
Which is way cool! Here's the increase in encapsulation I was talking about.
> If what you're proposing is that outsiders of the
> class be allowed to define functions like the above and access the
> internals of the class, then you might as well propose that the
> keyword private and the notion of data hiding be removed altogether...
No, that's not what he proposes. Did you read the web page?
Andrei
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Mon, 21 May 2001 18:51:30 GMT Raw View
"James Kuyper Jr." <kuyper@wizard.net> wrote in message
news:3B067663.19FA7DA@wizard.net...
> sabre@nondot.org wrote:
> ...
> > Which addresses several weaknesses of C++ (f.e. you can't extend a class
> > without modifying the class definition) while imposing little extra work
>
> That's eather false, or not a weakness, depending upon what you mean. In
> one sense, it's perfectly possible to extend a class definition - the
> process is called inheritance.
... along with the horrible dependencies and caveats that accompany
inheritance. No thanks, Sir.
> Not being able to extend a class definition except by inheritance is a
> strength, not a weakness, because it improves the predictability of a
> design. After reading a class definition from beginning to end, a C++
> designer knows precisely what the members of a class are, and that
> there's nothing a user can do (modulo Murphy vs. Machiavelli, of course)
> to add members that would change the behavior of the code. By careful
> use of access restrictions, a developer can guarantee that the parts of
> a class that need to work in a particular way are hidden from outside
> interference, while providing all the external handles needed to make
> the class extensible through inheritance.
The first thing to mention here is that his proposal doesn't affect access
rules. Class writers will enjoy the same privacy as before.
Because nobody mentioned the obvious connection, I will take the step to
mention Scott Meyers' article "How Non-Member Functions Increase
Encapsulation" in CUJ on Feb 2000
(http://www.cuj.com/articles/2000/0002/0002c/0002c.htm). That article makes
a very convincing argument for Chris' proposal.
The second thing to mention is that indeed the proposal does change things.
Consider:
class Dog
{
public:
void Bark(unsigned int);
...
};
#include "DogTools.h"
Now if you invoke:
Dog puppy;
puppy.Bark(10);
a different function will be included if DogTools.h contains a prototype:
void Bark(Dog&, int);
I don't see this as a problem because I'm already used to (and am enjoying a
great deal) overloading in the free functions space. I understand this can
be unsettling for some, but then, you can't please everyone.
I personally found the member function syntax and access rules annoying. I
consider them naive, harkening back to the very early days of C++ when
people didn't even realize that things like 'virtual' and 'this' are needed.
Back in those days it was so cool to write obj.Fun() instead of Fun(obj)...
Allowing equivalent notations for members and nonmembers would reduce
inheritance abuse, extirpate the "obese class" syndrome, make generic
programming a whole lot easier and more powerful, and increase the joy of
programming in C++.
Andrei
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 21 May 2001 15:09:43 -0400 Raw View
"James Kuyper Jr." <kuyper@wizard.net> wrote in message
news:3B08372F.67692B76@wizard.net...
[snip]
> No, I'd begin to have a greater appreciation for the lack of such a
> facility. If you could reopen the class definition, you could radically
> change the behavior of code written by the original designer, in ways
> that designer never anticipated. By closing the class definition, and
> allowing extensions to a class only through inheritance or containment,
> C++ is a far safer programming environment then it would be if class
> definitions could be re-opened.
But we're not talking about reopening a class' internals. We're talking
about implementing utility functions in terms of the existing public
functions, while offering syntactic consistency. That is definitely a good
thing and does not have anything to do with radically changing the behavior
of the code etc. Again, I recommend reading Scott Meyers' article that I
mentioned in the other post.
Andrei
------------
Check out THE C++ Seminar: 3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar/
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: James Kanze <James.Kanze@dresdner-bank.com>
Date: 22 May 01 05:23:23 GMT Raw View
Dietmar Kuehl wrote:
> Carlos Moreno wrote:
> > While sacrificing encapsulation and all the convenience of OO
> > programming.
> Not that I'm much in favour of this idea but this is an unjustified
> criticism: There was no mention that global functions get special
> rights just because they can be called using member notation! All
> this proposal is about is to change the name lookup such that global
> functions are considered when using member notion (and, possibly,
> vice versa; I'm not clear about that one). There is nothing said
> which would grant special rights to the global functions.
I thought (but I could be wrong) that it was the reverse that was
proposed; that member functions could be written using global function
syntax, with the base object as the first parameter.
Personally, I wouldn't use this if it were available. I don't like
the idea that a.f(b,c) and f(a,b,c) call exactly the same function;
overloading is confusing enough as is. And I share Francis'
hesitations about touching anything that involves name lookup.
There are some legitimate arguments (from Scott Meyer, among others)
that all function calls should have the form f(a,b,c). I can
sympathize with them, although I personally like the current syntax.
However, I think it's too late to change now. We can't ban the
current form, and having two forms would probably lead to too much
confusion.
--
James Kanze mailto:kanze@gabi-soft.de
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org>
Date: 22 May 01 07:57:46 GMT Raw View
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
An appealing idea.
However, couple of questions/points. Given:
-------
struct Base
{
void method() { cout << "Base"; }
};
struct Derived : Base
{
};
void method(Derived *d) { cout << "Derived"; }
--------
and:
Derived d;
d.method();
Would this print "Base", on the grounds that members have priority over
globals, or "Derived", on the grounds that the pseudo-member
Derived::method() hides the method in Base ?
Similarly, given:
-------
struct Base
{
// NB: virtual this time
virtual void method() { cout << "Base"; }
};
void method(Derived *d) { cout << "Derived"; }
struct Derived : Base
{
void otherMethod() { this->method(); }
};
--------
and:
d.otherMethod();
Would the hiding still take place ? I'm assuming that globals can't take
part in the virtual method mechanism.
Another awkward case (I think):
--------
struct Base
{
void method() { cout << "Base"; }
};
struct Intermediate : Base
{
};
void method(Intermediate *i) { cout << "Ha Ha!"; }
struct Derived : private Intermediate
{
void otherMethod() { this->method(); }
};
--------
Should the presence of the pseudo-member, Intermediate::method(), be able to
change the behaviour of Derived::otherMethod() ?
I suspect that these examples show that it'd be safer and less unexpected
for globals never to be considered when there was any candidate member
available. But that would seem to reduce the power of your proposal
considerably, which would be a great shame.
One other thing, I think there might be some problems around the area of
pointers to virtual methods.
-- chris
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "glancaster" <glancaster@ntlworld.com>
Date: 22 May 01 08:15:01 GMT Raw View
Just some small clarifications.
Garry Lancaster:
> > I would be interested to know what the point of thiscall is really - MS
use
> > it to place the this pointer in a register rather than on the stack but
this
> > makes it slower than their generally useable __fastcall.
Chris Lattner wrote:
> Really, I don't see how thiscall would be different than fastcall. The
> general point is the same: pass stuff in registers if you can. I don't
see
> how "this" is any different for a member function...
I should have been clearer. thiscall currently passes everything on the
stack apart from the this pointer, __fastcall passes everything it can in
registers with everything else on the stack and the other one (__stdcall I
think) passes everything on the stack. So, they're all currently different.
But as you say, this is no problem if breaking binary compatibility is
allowed.
> > Notes:
> > 1. For example, member functions hiding the correct Koenig lookup
accessible
> > function if they share the same name, one of the "swap problems". Thanks
to
> > Alan Griffiths for explaining this in ACCU's Overload magazine issue 41.
> I think the problem there is that Koenig lookup provides more room for
> ambiguity (as this proposal might). C++ chooses to error out on ambiguity
> rather than make a guess, simply because it doesn't want "suprise"
> behaviour later in the development cycle. I believe this to be a very
> very very good thing. ;)
I agree but this isn't the problem to which I was, admittedly rather
vaguely, alluding.
In Alan's article he explains how a member function hides a global function
only reachable through Koenig lookup, if they have the same name, *even if
their signatures are completely different*. The last bit is the pain really
and can lead to nasty surprises for the (non-language lawyer) coder.
In a sense this is good news for your proposal, as it makes a
reconsideration of the rules more likely.
Kind regards
Garry Lancaster
Codemill Ltd
Visit our web site at http://www.codemill.net
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: =?iso-8859-1?Q?Andr=E9_P=F6nitz?= <poenitz@htwm.de>
Date: 22 May 2001 12:17:19 -0400 Raw View
In comp.std.c++ Carlos Moreno <moreno@mochima.com> wrote:
> While sacrificing encapsulation and all the convenience of OO
> programming.
Not at all.
Look at it as a means to _really_ hide private helper functions of a
class from its declaration. Currently you are forced to expose the
names of such functions in the class interface. If you are allowed to use
global functions with the same syntax as member functions you do not need
to expose your private member functions and you do not have the "penalty"
of inconsistent syntax.
So this would in fact _help_ encapsulation.
Andre'
--
Andr P nitz ............................................. poenitz@htwm.de
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: sabre@nondot.org
Date: 18 May 2001 10:56:56 -0400 Raw View
This is a quick writeup I did for an idea that I would really like
added to C++'0x (I haven't seen it mentioned before):
http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
Basically, it proposes making these two forms equivalent for invoking
a method:
a.foo(b, c, d);
foo(a, b, c, d);
Which addresses several weaknesses of C++ (f.e. you can't extend a class
without modifying the class definition) while imposing little extra work
on compiler implementors, and costing no runtime performance. It also
helps address the sort(list) vs list.sort() issue, in a very different
way from previous posts.
I can't wait to be shot down. ;)
-Chris
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Mike Smith" <smithmc@DONTSPAMONMEmichaelsmith.org>
Date: 19 May 01 10:56:53 GMT Raw View
<sabre@nondot.org> wrote in message
news:DZ3N6.6492$ki5.89991@vixen.cso.uiuc.edu...
>
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition) while imposing little extra work
That may not be universally considered a weakness...
--
Mike Smith
One man's theology is another man's belly laugh. --R. A. Heinlein
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "glancaster" <glancaster@ntlworld.com>
Date: 19 May 01 10:58:11 GMT Raw View
Chris Lattner wrote:
> This is a quick writeup I did for an idea that I would really like
> added to C++'0x (I haven't seen it mentioned before):
>
> http://www.nondot.org/sabre/Projects/CXX/NameLookup.html
>
> Basically, it proposes making these two forms equivalent for invoking
> a method:
>
> a.foo(b, c, d);
> foo(a, b, c, d);
>
> Which addresses several weaknesses of C++ (f.e. you can't extend a class
> without modifying the class definition) while imposing little extra work
> on compiler implementors, and costing no runtime performance. It also
> helps address the sort(list) vs list.sort() issue, in a very different
> way from previous posts.
>
> I can't wait to be shot down. ;)
I actually think it's a good idea. I've been thinking along similar lines a
bit recently too. To me at least it seems to have some parallels with Koenig
lookup and also with the "interface principle" Herb Sutter talked about at
the recent ACCU conference (although I wouldn't want to put words into his
mouth).
Another advantage of this is that, except for virtual functions, member
function pointers and non-member function pointers become compatible
(provided the rest of the signatures are compatible). Member function
pointers are currently IMHO syntactic and efficiency nightmares yet they're
important for callbacks/events - the kind of thing Borland C++ Builder uses
the non-standard __closure extension for.
The disadvantages to the scheme I can see:
1. You point this out yourself in passing - references are sometimes *but
not always* implemented as pointers. I would be happier if the first
parameter in a "member-compatible global" function always had to be a
pointer. Don't allow references there.
2. Currently implementers are free to implement a special calling convention
for member functions. MS call theirs thiscall. This affects your plans for
binary compatibility between the two kinds of function call and
interoperability of the two different styles of definition and declaration
i.e.
struct A
{
void mem_fn(int); // Uses thiscall
};
void global_fn(A, int); // Doesn't use thiscall.
void mem_fn(A, int) {} // Wrong: calling convention mismatch.
void A::global_fn(int) {} // ditto
I wasn't sure if you were suggesting this should work or not. If you
continue to allow thiscall, it never will (portably).
thiscall also destroys my idea of compatibility of function pointers.
I would be interested to know what the point of thiscall is really - MS use
it to place the this pointer in a register rather than on the stack but this
makes it slower than their generally useable __fastcall. AFAIK thiscall
could be phased out without too much pain, although if any compiler vendors
that are big on binary compatibility between releases (Sun?) actually use it
that could be a different story.
3. As you mention, it requires some changes to the existing function name
lookup rules. This is a very tricky area, and "The Design & Evolution of
C++" tells how long and hard the creators of C++ tried to get it right. But
there are other problems with the existing rules [1] so I guess these may be
up for review even without your proposal.
4. It builds bridges across namespaces even more than Koenig lookup, because
now global functions effectively become members of up to two namespaces -
the one they are defined in and the one to which their first parameter
belongs. I *think* this is a good thing, but I'm not totally sure.
But overall I like it.
Kind regards
Garry Lancaster
Codemill Ltd
mailto << "glancaster" << at << "codemill" << dot << "net";
Visit our web site at http://www.codemill.net
Notes:
1. For example, member functions hiding the correct Koenig lookup accessible
function if they share the same name, one of the "swap problems". Thanks to
Alan Griffiths for explaining this in ACCU's Overload magazine issue 41.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]