todd@Quotron.COM (Todd Booth) (03/24/91)
Consider the following struct:
struct S {
void operator<<(char p1) { cout << p1; }
};
S *o2 = new S;
o2 << 'a'; // error <--- How can I resolve this?
*o2 << 'a'; // no problem, but ugly
S o1;
o1 << 'a'; // no problem
thanks,
--todd
--
todd (booth)
todd@quotron.com 213 302-4368
gyro@kestrel.edu (Scott Layson) (03/24/91)
In article <todd.669759003@premises1.Quotron.COM> todd@Quotron.COM (Todd Booth) writes: >Consider the following struct: > >struct S { > void operator<<(char p1) { cout << p1; } >}; > >S *o2 = new S; >o2 << 'a'; // error <--- How can I resolve this? >*o2 << 'a'; // no problem, but ugly > >S o1; >o1 << 'a'; // no problem I have used a two-level class structure in cases like this: struct S { struct S_impl { // ... whatever } *impl; public: void operator<<(char p1) { cout << p1; } // constructors etc. }; This is a pretty good solution, but it starts to break down when you want to have parallel hierarchies of inner and outer classes, because `impl' (the sole data member of S which will be inherited by all of its derived classes) is always of type `S_impl*', while you will want it to be a pointer to the appropriate derived class of `S_impl'. Casting `impl' to be the right type is a bit messy but works, until you start using multiple inheritance with virtual base classes, at which point you're totally up a tree. For these reasons I have toyed with the idea of proposing to the committee a system for declaring "member functions" on the type `C*' where C is some class, so that your first example could be made to work without the two-level class structure. Unfortunately, I have never managed to come up with a proposal I find adequately elegant. -- Scott Layson Burson Gyro@Reasoning.COM
Ari.Huttunen@hut.fi (Ari Juhani Huttunen) (03/25/91)
In article <1991Mar24.074308.28666@kestrel.edu> gyro@kestrel.edu (Scott Layson) writes: >For these reasons I have toyed with the idea of proposing to the >committee a system for declaring "member functions" on the type `C*' >where C is some class, so that your first example could be made to >work without the two-level class structure. Unfortunately, I have >never managed to come up with a proposal I find adequately elegant. How about this one? struct S { friend void operator<<(S *s, char p1) { *s << p1; } void operator<<(char p1) { cout << p1; } }; -- Ari Huttunen, email: Ari.Huttunen@hut.fi, phone: 90-7285944
gyro@kestrel.edu (Scott Layson) (03/26/91)
In article <ARI.HUTTUNEN.91Mar24212428@punisher.hut.fi> Ari.Huttunen@hut.fi (Ari Juhani Huttunen) writes: >In article <1991Mar24.074308.28666@kestrel.edu> gyro@kestrel.edu (Scott Layson) writes: > >>For these reasons I have toyed with the idea of proposing to the >>committee a system for declaring "member functions" on the type `C*' >>where C is some class, so that your first example could be made to >>work without the two-level class structure. Unfortunately, I have >>never managed to come up with a proposal I find adequately elegant. > >How about this one? > >struct S { >friend void operator<<(S *s, char p1) { *s << p1; } > void operator<<(char p1) { cout << p1; } >}; Ah. Indeed that works for the specific example under consideration. I was thinking of the example I had encountered in the past, where I basically wanted to hide from the outside world the fact that a class was implemented as a pointer. So, I wanted to say `obj.mfunc()' rather than `obj->mfunc()'. Granted, overloadable `.' would accomplish this. I seem to recall, however, that that still isn't all I wanted. Let me think about this. -- Scott Layson Burson Gyro@Reasoning.COM
gyro@kestrel.edu (Scott Layson Burson) (03/26/91)
In article <1991Mar25.192002.6392@kestrel.edu> I wrote: >In article <ARI.HUTTUNEN.91Mar24212428@punisher.hut.fi> Ari.Huttunen@hut.fi (Ari Juhani Huttunen) writes: >>How about this one? >> >>struct S { >>friend void operator<<(S *s, char p1) { *s << p1; } >> void operator<<(char p1) { cout << p1; } >>}; > >Ah. Indeed that works for the specific example under consideration. >I was thinking of the example I had encountered in the past, where I >basically wanted to hide from the outside world the fact that a class >was implemented as a pointer. So, I wanted to say `obj.mfunc()' >rather than `obj->mfunc()'. > >Granted, overloadable `.' would accomplish this. I seem to recall, >however, that that still isn't all I wanted. Let me think about this. I must correct myself. Overloadable `.' would do nothing of the kind, insofar as I understand the current proposal, because a pointer type cannot have member functions and therefore cannot, in particular, overload `operator.'. I think the bottom line here is that C++ provides very well for the "value model" of objects, but not very well for the "pointer model" (see the commentary that starts on p.191 of E&S). There are good reasons for providing the value model, which I don't disagree with, but I think the pointer model got unnecessarily left out in the cold. -- Scott Layson Burson Gyro@Reasoning.COM
Ari.Huttunen@hut.fi (Ari Juhani Huttunen) (03/26/91)
In article <1991Mar25.192002.6392@kestrel.edu> gyro@kestrel.edu (Scott Layson) writes:
Ari>How about this one?
Ari>
Ari>struct S {
Ari>friend void operator<<(S *s, char p1) { *s << p1; }
Ari> void operator<<(char p1) { cout << p1; }
Ari>};
Scott>Ah. Indeed that works for the specific example under consideration.
No, this does not work. Or at least it does not work with g++ 1.37.1. The
error is:
operator has no user-defined argument type
(meaning the friend operator.) Though I think this _should_ work.
--
Ari Huttunen, email: Ari.Huttunen@hut.fi, phone: 90-7285944
steve@taumet.com (Stephen Clamage) (03/28/91)
Ari.Huttunen@hut.fi (Ari Juhani Huttunen) writes: |Ari>struct S { |Ari>friend void operator<<(S *s, char p1) { *s << p1; } |Ari> void operator<<(char p1) { cout << p1; } |Ari>}; |No, this does not work. Or at least it does not work with g++ 1.37.1. The |error is: | operator has no user-defined argument type |(meaning the friend operator.) Though I think this _should_ work. It should _not_ work. It has always been a requirement that an overloaded operator function must have at least one parameter of class type. A pointer to a class type is not a class type. We can argue about whether the restriction should be relaxed (I don't believe it should be), but the language definition make the code illegal. -- Steve Clamage, TauMetric Corp, steve@taumet.com
jss@gold.kpc.com (Jerry Schwarz) (03/29/91)
In article <todd.669759003@premises1.Quotron.COM> todd@Quotron.COM (Todd Booth) writes:
*o2 << 'a'; // no problem, but ugly
Beauty is in the eye of the beholder. Having worked a lot with
ostream* variables I have written stuff like the above a lot and no
longer find it ugly. I certainly wouldn't contort my class
definitions in order to avoid it.
Jerry Schwarz