Topic: Virtual >> and <<
Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/06/28 Raw View
In article <3sbnj9$2ti@gabi.gabi-soft.fr>, J. Kanze <kanze@gabi-soft.fr> wrote:
>Jeff D. Koftinoff (jeffk@awinc.com) wrote:
>
>|> Absolutely! IMHO, iostreams is horrible.
>I sort of agree concerning the abuse of operator overloading, but I
>don't know of any other way to obtain the same functionality. They are
>amazingly easy to use and to extend in real situations, once you have
>learned them. There is a good, clear separation of the two separate
>functionalities, formatting, and shipping bytes in and out.
>
>What more do you want?
What is required in commercial I/O is full user
control of output at a level way beyond IOstream capability,
and full parsing with error handling of input according to rules way beyond
the primitive IOstream facilities. (Proof: the usual way to
do this involves using a GUI)
The saving grace of IOstreams is that you can and usually should
ignore the formatting completely and go straight to the transport.
The utility of iostream formating is _convenient_ for
things like debugging. Just don't push it to hard and don't
expect you can write robust commercial quality interactive IO
using it -- unless you want to win an obscufated C++ coding
competition.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/06/23 Raw View
In article <3rrtmo$20l@gabi.gabi-soft.fr>, J. Kanze <kanze@gabi-soft.fr> wrote:
>John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
>
> [Concerning formatted output...]
>|> Note that STL provides a superior interface, at least to
>|> output: using a user defined iterator one can output formatted
>|> floating point without silly inserter things:
>
>|> *FloatOut(cout, 10, 2)++ = 2.33;
>
>|> [I "made up" the FloatOut iterator and so can you. It is much
>|> easier than writing inserters. The easiest way to
>|> implement the above is to use sprintf :-]
>
>I'm curious how your FloatOut iterator (implemented on the basis of
>sprintf) handles (admittedly perverse) cases like:
>
> *FloatOut( cout , 500 , 10 )++ = 1e-305 ;
>
>Who does the memory management?
Use a fixed length buffer. Document the length restriction.
For floating point numbers this is no practical problem.
Sigh. There are of course other techniques which are
more robust but require a bit more work than
char buffer[1024];
assert(len < 500);
sprintf(buffer, "%*.*f", len, prec, val);
cout << buffer;
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/22 Raw View
Jeff D. Koftinoff (jeffk@awinc.com) wrote:
|> Absolutely! IMHO, iostreams is horrible. Lots of abuse of operator
|> overloading. Not easy to use in a real situation. Not easy to inherit. No
|> clear separation of abstract interfaces and implementation.
That's what I thought too. I only used them for the type safety. But
the more I push them, the more I appreciate the design. Jerry Schwarz
did a much better job of it than I could have.
I think that the biggest problem with iostream's is probably the lack of
good documentation and training material. I've not seen Steve Teele's
book (and have heard mixed comments about it), but most C++ texts seem
to mention them only in passing.
I sort of agree concerning the abuse of operator overloading, but I
don't know of any other way to obtain the same functionality. They are
amazingly easy to use and to extend in real situations, once you have
learned them. There is a good, clear separation of the two separate
functionalities, formatting, and shipping bytes in and out.
What more do you want?
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
--Beratung in industrieller Datenverarbeitung
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/22 Raw View
According to J. Kanze <kanze@gabi-soft.fr>:
> I think that the biggest problem with iostream's is probably the lack of
> good documentation and training material. I've not seen Steve Teele's
> book (and have heard mixed comments about it), but most C++ texts seem
> to mention them only in passing.
>
> I sort of agree concerning the abuse of operator overloading, but I
> don't know of any other way to obtain the same functionality. They are
> amazingly easy to use and to extend in real situations, once you have
> learned them. There is a good, clear separation of the two separate
> functionalities, formatting, and shipping bytes in and out.
>
> What more do you want?
Extensibility. :-)
I agree, I like most of the design of iostreams as well. I also
agree that much better documentation is necessary. I actually think
that the operator overloading is rather elegant(?). But the lack
of virtual functions make it nearly impossible to derive from them.
Classes like fstream and str(ing)stream only add the ability to
manipulate filebuf and strstreambuf's indirectly, and don't actually
change the fundamentals of the iostream (they couldn't even if you
wanted to).
The reason streambuf is such a useful class is because overflow()
and underflow() are virtual (among others). That gives me great
power to create a class for any device I like. The iostreams
need that same power.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/22 Raw View
According to Jeff D. Koftinoff <jeffk@awinc.com>:
> peter@chinook.physics.utoronto.ca (Peter Berdeklis) wrote:
> >According to Tony Cook <tony@online.tmx.com.au>:
> >>
> >> I'm not entirely sure that would resolve the problem - unless you
> >> want peek() and get() to be virtual as well (extractors can use
> >> these too).
> >
> >
> >Why not? Why should the standard put an unnecessary limitation on the
> >reuse of the standard library? None of my suggestions would violate
> >any _language_ rules - this is purely a question of the philosophy of
> >the std library.
> >
> >Many authors suggest that a proper OOP class would make virtual as
> >much of its interface as possible, so as to not limit its possible
> >reuse. The idea is that as the author of the class, you may not be
> >able to see the possibile uses or variations that its user might see.
> >Why should the authors of the std lib assume any different?
> >
> Absolutely! IMHO, iostreams is horrible. Lots of abuse of operator
> overloading. Not easy to use in a real situation. Not easy to inherit. No
> clear separation of abstract interfaces and implementation.
>
> The solution is to not use iostreams. Create your own streams. Streams that
> can handle different formats easily. Streams that can handle RTTI.
>
> Put the code that reads and writes your objects in a separate class
> hierarchy so it can be extended easily. Do things properly. I have.
>
> Here is one case of a 'standard' being in danger of not being used.
> We will have to create our OWN (non-ANSI) 'standard' that is good
> enough so people WILL use it.
Actually I've always found the std streams quite useful and fairly
easy to use, if not perfect. That doesn't mean I wouldn't like to
change them a bit (obviously <g>).
The thought of deriving my own stream class has of course crossed my
mind. However, it would mean not being able to reuse a lot of good,
old code. Also, the fact that the std streams are std is nothing to
sneeze at.
If I didn't think they were good enough to use I wouldn't have gone
through the grief of starting and supporting this thread. (At this
time I would like to thank all of you who have taken the time to
respond to this thread. :-)
Pete
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/23 Raw View
In article <3sdg53$3mp@metro.ucc.su.OZ.AU> maxtal@Physics.usyd.edu.au
(John Max Skaller) writes:
|> In article <3rrtmo$20l@gabi.gabi-soft.fr>, J. Kanze <kanze@gabi-soft.fr> wrote:
|> >John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
|> >
|> > [Concerning formatted output...]
|> >|> Note that STL provides a superior interface, at least to
|> >|> output: using a user defined iterator one can output formatted
|> >|> floating point without silly inserter things:
|> >
|> >|> *FloatOut(cout, 10, 2)++ = 2.33;
|> >
|> >|> [I "made up" the FloatOut iterator and so can you. It is much
|> >|> easier than writing inserters. The easiest way to
|> >|> implement the above is to use sprintf :-]
|> >
|> >I'm curious how your FloatOut iterator (implemented on the basis of
|> >sprintf) handles (admittedly perverse) cases like:
|> >
|> > *FloatOut( cout , 500 , 10 )++ = 1e-305 ;
|> >
|> >Who does the memory management?
|> Use a fixed length buffer. Document the length restriction.
|> For floating point numbers this is no practical problem.
I agree that using a fixed length buffer is not a problem for floating
point. The problem is enforcing the restriction when using sprintf.
|> Sigh. There are of course other techniques which are
|> more robust but require a bit more work than
|> char buffer[1024];
|> assert(len < 500);
|> sprintf(buffer, "%*.*f", len, prec, val);
|> cout << buffer;
My point is that, for what you are doing, iostream is in fact easier
to use than the printf family. It makes the safety checks for you.
(And if you are using a fixed length buffer, you don't have to worry
about freezing the buffer.) Thus:
ostrstream s ;
s << setw( len ) << setprecision( prec ) << val ;
cout << s.rdbuf() ;
Not only is iostream safer, in this case (exceptionally), the
resulting code is shorter and easier to understand. (If performance
is an issue, you may want to provide an on-stack buffer for the
ostrstream, to avoid the dynamic memory management.)
BTW, for those APL fans, who argue that less lines is always better:
cout << (ostrstream() << setw( len ) << setprecision( prec ) << val).rdbuf() ;
Personally, I like succinctness, but this is carrying it a little too
far for even my tastes:-).
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/20 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: According to Tony Cook <tony@online.tmx.com.au>:
: > The problem is that extractors are often _much_ more complex than
: > inserters, for example an inserter for complex might just be:
: > ostream &operator <<(ostream &os, complex v)
: > {
: > return os << '(' << v.r << ',' << v.i << ')';
: > }
: >
: > while an extractor might want to match any of the following:
: > <float> // just a real
: > <float>'i' // just imaginary
: > <float>'+'<float>'i' // fully complex
: > <float>'i+'<float> // and again - not as likely
: > '('<float>')' // just a real
: > '(,'<float>')' // imaginary
: > '('<float>','<float>')' // complex
: >
: > ...and imagine what might be required for inserters and extractors
: > for dates.
: >
: > So we have inserters that stream out - assuming formatted output and
: > the extract that streams it back in. I find it hard to beleive that
: > the NetStream binary extractor will work any way reliably as a fully
: > general formatted extractor.
: If you can write an extractor for a file then that same extractor will
: work for a NetStream. Show me an example of an extractor for complex
: that will not.
[Sorry about the delay - I had some hard disk problems]
#include <iostream.h>
#include "mycomplx.h"
/*
We want this to match the following:
<float>
<float>'i'
<float>'+'<float>'i'
<float>'i''+'<float>
<float>'-'<float>'i'
<float>'i''-'<float>
'('<ws><float><ws>','<ws><float><ws>')'
'('<ws><float><ws>')'
'('<ws>','<ws><float><ws>')'
'('<ws>','<ws><float><ws>')'
I also match:
'('<ws>','<ws>')'
<float> is whatever is read by operator>>(istream &, double &)
<ws> is optional whitespace (if skipws is set)
I don't allow whitespace in the non-bracketed formats as it would
make it difficult to separate on input.
*/
istream &operator>>(istream &is, complex &result)
{
// brackets?
char c;
is >> c;
if (c == '(')
{
// ok - we're in parens
is >> c; // should be ',' or start of <float>
if (c == ',')
{
result.r = 0.0;
}
else
{
is.putback(c);
is >> result.r;
is >> c; // should be ',' or ')'
}
if (c == ',')
{
is >> c;
if (c == ')')
{
result.i = 0.0;
}
else
{
is.putback(c);
is >> result.i;
is >> c; // c should be ')'
if (c != ')')
// error!!
is.clear(ios::badbit | is.rdstate());
}
}
else if (c == ')')
{
result.i = 0.0;
}
else
{
// error!!
is.clear(ios::badbit | is.rdstate());
// is this the right bit?
}
}
else
{
// we don't want to skip any whitespace in here
long saveFlags = is.flags();
is.setf(saveFlags & ~ios::skipws);
double temp;
is.putback(c);
is >> temp;
c = is.peek();
if (c == 'i')
{
is.get();
result.i = temp;
c = is.peek();
if (c == '+' || c== '-')
{
is >> result.r;
}
}
else if (c == '+' || c == '-')
{
is.get();
double tempImag;
is >> tempImag;
c = is.get();
if (c == 'i')
{
result.r = temp;
result.i = tempImag;
}
else
is.clear(ios::badbit | is.rdstate());
}
is.setf(saveFlags); // put it back the way we found it
}
return is;
}
This is a fairly simple extractor for complex - but notice that any
time that it does look-ahead to try to determine what is ahead of it
in the stream it may be reading part of the binary representation of
the double.
This is the primary problem with using the formatted input/output
classes for binary I/O.
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/06/20 Raw View
peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
>According to Tony Cook <tony@online.tmx.com.au>:
>> This is a fairly simple extractor for complex - but notice that any
>> time that it does look-ahead to try to determine what is ahead of it
>> in the stream it may be reading part of the binary representation of
>> the double.
[...]
>Tony, all the test that you perform in your inserter are on the
>assumption that the user may have editted the file by hand (I think),
>because the conditions do not match your extractor.
The extractor accepts a more general syntax than just the output
of the inserter, but that is a common and useful thing for formatted I/O.
The fact that it doesn't work for binary I/O shows that attempting
to use formatted I/O routines for binary I/O is a bad idea, not that
there is anything wrong with Tony Cook's inserter.
>However, none
>of that would be necessary for a NetStream since the other side will
>recieve exactly what your extractor sent.
Yes, that's the point! None of this is necessary for binary streams -
in fact it doesn't even work at all for binary streams - but it _is_
necessary for formatted streams. That's why trying to reuse formatted
I/O routines to do binary I/O is a bad idea.
>I didn't say that a NetStream class was perfect, but the user could always
>flag it to send only char data if it wasn't working right. In any case
>that should be up to _me_ and my _user_, not the std. Virtual >> and <<
>would allow that.
The idea is Broken As Designed (BAD).
A NetStream class like that would be a festering design flaw just
waiting to erupt into a genuine bug. C++ is hard enough already;
the standard should not encourage people to fall into those sort
of traps.
--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/20 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: Tony, all the test that you perform in your inserter are on the
: assumption that the user may have editted the file by hand (I think),
: because the conditions do not match your extractor. However, none
: of that would be necessary for a NetStream since the other side will
: recieve exactly what your extractor sent.
No - they assume that we want to accept input from a _user_ in more
than just the form we output.
: That, of course, is not in and of itself reason to assume that it
: will not fail. However, just as a note, all of the conditions that
: you test would pass without problem if the inserter is reading exactly
: what the extractor wrote.
They don't - for example for output with NetStream we have:
'('<bindouble>','<bindouble>')'
where <bindouble> is the NetStream binary representation of a double
- I am assuming simply a binary dump in IEEE form (litte- or
big-endian doesn't matter).
What happens if the first character output for the first <bindouble>
is 0x2C (ie. (int)',') - the parser will read that and treat it as
the:
'(' ','<bindouble>')'
form (and probably fail).
A similar problem occurs if the first character of the second.
: Furthermore, there is nothing stopping me from sending type information
: through the stream. An extra byte indicating a float would still be less
: bandwidth than sending it as char data. Of course, this kind of bloats
: single char's but you could have a single byte for strings, so that wouldn't
: be too bad.
I'm not entirely sure that would resolve the problem - unless you
want peek() and get() to be virtual as well (extractors can use
these too).
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/21 Raw View
According to Fergus Henderson <fjh@munta.cs.mu.OZ.AU>:
> peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
>
> >According to Tony Cook <tony@online.tmx.com.au>:
> >> This is a fairly simple extractor for complex - but notice that any
> >> time that it does look-ahead to try to determine what is ahead of it
> >> in the stream it may be reading part of the binary representation of
> >> the double.
> [...]
> >Tony, all the test that you perform in your inserter are on the
> >assumption that the user may have editted the file by hand (I think),
> >because the conditions do not match your extractor.
>
> The extractor accepts a more general syntax than just the output
> of the inserter, but that is a common and useful thing for formatted I/O.
> The fact that it doesn't work for binary I/O shows that attempting
> to use formatted I/O routines for binary I/O is a bad idea, not that
> there is anything wrong with Tony Cook's inserter.
>
Please don't misunderstand me. I was not criticizing Tony's inserter,
just suggesting that it would work anyway.
> >However, none
> >of that would be necessary for a NetStream since the other side will
> >recieve exactly what your extractor sent.
>
> Yes, that's the point! None of this is necessary for binary streams -
> in fact it doesn't even work at all for binary streams - but it _is_
> necessary for formatted streams. That's why trying to reuse formatted
> I/O routines to do binary I/O is a bad idea.
>
As I've said before, changing to and from network representation is a
form of formatting. To and from character repersentation is not the
only form of formatting you can do.
The point is that you cannot necessarily read the data as binary if
it's coming over the net - it must be formatted to match the machine's
representation, just as with character data.
This may not be the only application where overriding >> and <<
might be useful. I can't honestly think of another ex., and maybe
you can't either, but should the standard limit someone else's
(better) idea?
> >I didn't say that a NetStream class was perfect, but the user could always
> >flag it to send only char data if it wasn't working right. In any case
> >that should be up to _me_ and my _user_, not the std. Virtual >> and <<
> >would allow that.
>
> The idea is Broken As Designed (BAD).
> A NetStream class like that would be a festering design flaw just
> waiting to erupt into a genuine bug. C++ is hard enough already;
> the standard should not encourage people to fall into those sort
> of traps.
Even if my NetStream class is a bad idea, that has nothing to do
with whether or not >> and << should be virtual. If C++ claims to
be an object oriented language, then the kind of flexibility expected
in user classes should also be expected in the standard.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/21 Raw View
According to Tony Cook <tony@online.tmx.com.au>:
> Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
> : Furthermore, there is nothing stopping me from sending type information
> : through the stream. An extra byte indicating a float would still be less
> : bandwidth than sending it as char data. Of course, this kind of bloats
> : single char's but you could have a single byte for strings, so that wouldn't
> : be too bad.
>
> I'm not entirely sure that would resolve the problem - unless you
> want peek() and get() to be virtual as well (extractors can use
> these too).
Why not? Why should the standard put an unnecessary limitation on the
reuse of the standard library? None of my suggestions would violate
any _language_ rules - this is purely a question of the philosophy of
the std library.
Many authors suggest that a proper OOP class would make virtual as
much of its interface as possible, so as to not limit its possible
reuse. The idea is that as the author of the class, you may not be
able to see the possibile uses or variations that its user might see.
Why should the authors of the std lib assume any different?
Pete
Author: Jeff D. Koftinoff <jeffk@awinc.com>
Date: 1995/06/21 Raw View
peter@chinook.physics.utoronto.ca (Peter Berdeklis) wrote:
>According to Tony Cook <tony@online.tmx.com.au>:
>>
>> I'm not entirely sure that would resolve the problem - unless you
>> want peek() and get() to be virtual as well (extractors can use
>> these too).
>
>
>Why not? Why should the standard put an unnecessary limitation on the
>reuse of the standard library? None of my suggestions would violate
>any _language_ rules - this is purely a question of the philosophy of
>the std library.
>
>Many authors suggest that a proper OOP class would make virtual as
>much of its interface as possible, so as to not limit its possible
>reuse. The idea is that as the author of the class, you may not be
>able to see the possibile uses or variations that its user might see.
>Why should the authors of the std lib assume any different?
>
>
>
>Pete
>
Absolutely! IMHO, iostreams is horrible. Lots of abuse of operator
overloading. Not easy to use in a real situation. Not easy to inherit. No
clear separation of abstract interfaces and implementation.
The solution is to not use iostreams. Create your own streams. Streams that
can handle different formats easily. Streams that can handle RTTI.
Put the code that reads and writes your objects in a separate class
hierarchy so it can be extended easily. Do things properly. I have.
Here is one case of a 'standard' being in danger of not being used.
We will have to create our OWN (non-ANSI) 'standard' that is good
enough so people WILL use it.
-------------------------------------------------------
---------- Jeff Koftinoff --- jeffk@awinc.com ---------
--- Multimedia and Embedded Systems Programming ---
--- http://www.xmission.com/~seer/jdksoftware/ ---
-------------------------------------------------------
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/20 Raw View
According to Tony Cook <tony@online.tmx.com.au>:
> Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
> : According to Tony Cook <tony@online.tmx.com.au>:
> : > The problem is that extractors are often _much_ more complex than
> : > inserters, for example an inserter for complex might just be:
> : > ostream &operator <<(ostream &os, complex v)
> : > {
> : > return os << '(' << v.r << ',' << v.i << ')';
> : > }
> : >
> : > while an extractor might want to match any of the following:
> : > <float> // just a real
> : > <float>'i' // just imaginary
> : > <float>'+'<float>'i' // fully complex
> : > <float>'i+'<float> // and again - not as likely
> : > '('<float>')' // just a real
> : > '(,'<float>')' // imaginary
> : > '('<float>','<float>')' // complex
> : >
> : > ...and imagine what might be required for inserters and extractors
> : > for dates.
> : >
> : > So we have inserters that stream out - assuming formatted output and
> : > the extract that streams it back in. I find it hard to beleive that
> : > the NetStream binary extractor will work any way reliably as a fully
> : > general formatted extractor.
>
> : If you can write an extractor for a file then that same extractor will
> : work for a NetStream. Show me an example of an extractor for complex
> : that will not.
>
> [Sorry about the delay - I had some hard disk problems]
>
> #include <iostream.h>
>
> #include "mycomplx.h"
>
> /*
> We want this to match the following:
> <float>
> <float>'i'
> <float>'+'<float>'i'
> <float>'i''+'<float>
> <float>'-'<float>'i'
> <float>'i''-'<float>
> '('<ws><float><ws>','<ws><float><ws>')'
> '('<ws><float><ws>')'
> '('<ws>','<ws><float><ws>')'
> '('<ws>','<ws><float><ws>')'
>
> I also match:
> '('<ws>','<ws>')'
>
> <float> is whatever is read by operator>>(istream &, double &)
> <ws> is optional whitespace (if skipws is set)
>
> I don't allow whitespace in the non-bracketed formats as it would
> make it difficult to separate on input.
>
> */
> istream &operator>>(istream &is, complex &result)
> {
> // brackets?
> char c;
> is >> c;
> if (c == '(')
> {
> // ok - we're in parens
[snip]
> }
> return is;
> }
>
> This is a fairly simple extractor for complex - but notice that any
> time that it does look-ahead to try to determine what is ahead of it
> in the stream it may be reading part of the binary representation of
> the double.
>
> This is the primary problem with using the formatted input/output
> classes for binary I/O.
Tony, all the test that you perform in your inserter are on the
assumption that the user may have editted the file by hand (I think),
because the conditions do not match your extractor. However, none
of that would be necessary for a NetStream since the other side will
recieve exactly what your extractor sent.
That, of course, is not in and of itself reason to assume that it
will not fail. However, just as a note, all of the conditions that
you test would pass without problem if the inserter is reading exactly
what the extractor wrote.
Furthermore, there is nothing stopping me from sending type information
through the stream. An extra byte indicating a float would still be less
bandwidth than sending it as char data. Of course, this kind of bloats
single char's but you could have a single byte for strings, so that wouldn't
be too bad.
I didn't say that a NetStream class was perfect, but the user could always
flag it to send only char data if it wasn't working right. In any case
that should be up to _me_ and my _user_, not the std. Virtual >> and <<
would allow that.
Thanks for your time Tony.
Pete
Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/06/15 Raw View
In article <DA1Inr.1Jn@info.physics.utoronto.ca>,
Peter Berdeklis <peter@chinook.physics.utoronto.ca> wrote:
>According to Tony Cook <tony@online.tmx.com.au>:
>> The problem is that extractors are often _much_ more complex than
>> inserters, for example an inserter for complex might just be:
No. The problem with extractors -- and iostreams in general
-- is that the idea is unsound (IMHO of course).
Most complicated output requires parameters -- there is no
proper way to send an argument list to
an ostream. Complicated input requires a parser.
Note that STL provides a superior interface, at least to
output: using a user defined iterator one can output formatted
floating point without silly inserter things:
*FloatOut(cout, 10, 2)++ = 2.33;
[I "made up" the FloatOut iterator and so can you. It is much
easier than writing inserters. The easiest way to
implement the above is to use sprintf :-]
I am currently examining how one might interface a parser
to a stream using STL. It seems clear interfacing
an arbitrary regular language using "maximal munch" tokenisation
is not impossible and within the scope of the "average" smart
C++ programmer to implement. Full context free parsing
is actually considerably easier but slower.
[BTW: parsing and translation more or less require nested functions,
coroutines and discriminated unions to implement cleanly,
in particular "IO" would be done using monitor objects interfaced
by STL iterators which also exchange control to get the
data flowing through the system]
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/15 Raw View
John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
: In article <DA1Inr.1Jn@info.physics.utoronto.ca>,
: Peter Berdeklis <peter@chinook.physics.utoronto.ca> wrote:
: >According to Tony Cook <tony@online.tmx.com.au>:
: >> The problem is that extractors are often _much_ more complex than
: >> inserters, for example an inserter for complex might just be:
: No. The problem with extractors -- and iostreams in general
: -- is that the idea is unsound (IMHO of course).
: Most complicated output requires parameters -- there is no
: proper way to send an argument list to
: an ostream. Complicated input requires a parser.
The point I was trying to make is that a robust parser for any type
requires more work than the output for such a type.
Leaving behind NetStream for now, a simple example is integer output
and input.
Output can assume the integer exists and is valid (its just a bit
pattern).
Input needs to consider invalid characters on input, special cases
like a leading '+', and overflow.
: Note that STL provides a superior interface, at least to
: output: using a user defined iterator one can output formatted
: floating point without silly inserter things:
: *FloatOut(cout, 10, 2)++ = 2.33;
Neat.
: [BTW: parsing and translation more or less require nested functions,
: coroutines and discriminated unions to implement cleanly,
: in particular "IO" would be done using monitor objects interfaced
: by STL iterators which also exchange control to get the
: data flowing through the system]
[Are you talking about taking the output from one 'thread' and using
it as the input for another?]
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/16 Raw View
John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
[Concerning formatted output...]
|> Note that STL provides a superior interface, at least to
|> output: using a user defined iterator one can output formatted
|> floating point without silly inserter things:
|> *FloatOut(cout, 10, 2)++ = 2.33;
|> [I "made up" the FloatOut iterator and so can you. It is much
|> easier than writing inserters. The easiest way to
|> implement the above is to use sprintf :-]
I'm curious how your FloatOut iterator (implemented on the basis of
sprintf) handles (admittedly perverse) cases like:
*FloatOut( cout , 500 , 10 )++ = 1e-305 ;
Who does the memory management? (I'm not saying that it cannot be done,
just that it is considerably easier to use ostringstream than sprintf,
at least if you want a robust program.)
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
--Beratung in industrieller Datenverarbeitung
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/13 Raw View
In article <DA2nJ6.Ho9@info.physics.utoronto.ca>
peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
|> According to J. Kanze <kanze@gabi-soft.fr>:
|> > Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
|> > |> By deriving from ostream and overriding a virtual << and >>, a class
|> > |> does need to know that NetStream exist, the same way it can't
|> > |> distinguish between an fstream, strstream or stringstream. Deriving
|> > |> NetStream as a parallel class requires that objects know that
|> > |> NetStream exists, which I consider _network awareness_, and an
|> > |> unneccessary violation of encapsulation and data hiding.
|> >
|> > This is where we disagree. I do not think it possible for an object to
|> > generate an adequate format for a network without being network aware.
|> ^^^^^^^^
|> Yes James, this is where we disagree. IMHO there is a significant
|> difference between _adequate_ and _optimum_. Any class should be
|> capable of outputting an adequate format, even if it sends all
|> character data. Of course, this may not be optimum. However, a
|> NetStream class would cover both cases sufficiently.
Put this way, I think you are right. While it would be nice if all
objects were net aware, and used an optimal format, I can see that
using a character format is generally better than not being able to
use the class at all (baring a considerable amount of work).
I can still think of a few special cases where you scheme would fail,
but I think they would be relatively rare. (I've never actually had
to use one.)
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/11 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
: >
: > I guess it depends on what you are doing, but most of my operator<<'s
: > only use ostream::put, and insert characters one at a time. They do
: > real format conversion, at least most of the time.
: >
: James, I'ld like to see an example. I have trouble seeing how doing
: your own conversion, instead of using conversion operators already
: written and debugged for you, is not a waste of time.
:
: > Even classical examples, like complex, which do use formatted output,
: > may not do what you want. For example, complex will typically output
: > something like `(r,i)', where r and i are output using formatted
: > output as doubles.
: >
: > Would such an insertor do what you want for the NetStream? Does your
: > NetStream really want an ASCII '(', its own representation of double,
: > and ASCII ',', its own representation of double, and finally and ASCII
: > ')'? I seriously doubt it.
: ^^^^^^^^^^^^^^^^^^^^^
: As a matter of fact James, my NetStream class couldn't care less what it
: is that you stream out, as long as it can stream itself back in.
: If you have a complex class that outputs itself as '(r,i)', then I assume
: that your overloaded extractors know that and will ignore the appropriate
: characters when it reads from the stream. Otherwise, how does a complex
: class read itself from a file?
: The idea is to make the NetStream class act _exactly_ like a regular C++
: stream. Therefore _any_ class that is aware of streams would by default
: be aware of networks.
The problem is that extractors are often _much_ more complex than
inserters, for example an inserter for complex might just be:
ostream &operator <<(ostream &os, complex v)
{
return os << '(' << v.r << ',' << v.i << ')';
}
while an extractor might want to match any of the following:
<float> // just a real
<float>'i' // just imaginary
<float>'+'<float>'i' // fully complex
<float>'i+'<float> // and again - not as likely
'('<float>')' // just a real
'(,'<float>')' // imaginary
'('<float>','<float>')' // complex
...and imagine what might be required for inserters and extractors
for dates.
So we have inserters that stream out - assuming formatted output and
the extract that streams it back in. I find it hard to beleive that
the NetStream binary extractor will work any way reliably as a fully
general formatted extractor.
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/12 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
|> According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
|> > We don't seem to be communicating very well. Perhaps I misunderstand
|> > your NetStream, or perhaps I have not really explained myself clearly.
|> >
|> > I am supposing that your NetStream data ends up on something like a
|> > socket, or a serial link between two processors. I am also supposing
|> > that for bandwidth reasons, you do not want an ASCII representation
|> > (otherwise, why bother with any special formatting).
|> >
|> > Now, I consider objects typical of those I write. For the most part,
|> > they have an operator<< (provided by me). For the most part, they
|> > contain enum's. The operator<< outputs an ASCII (symbolic)
|> > representation of the enum value, typically about 8 bytes. For
|> > outputting to a socket or stream where bandwidth is a consideration, I
|> > would not consider this an acceptable representation; I would normally
|> > only output a single byte with the binary internal representation.
|> >
|> > Also, since the length of the ASCII representations is variable, an
|> > object which contains several such enum's will output a separator
|> > between each one. When outputting to a stream/socket, such a
|> > separator is not necessary.
|> >
|> > Does this correspond to your application? If not, could you please
|> > indicate to me where I have misunderstood the application. If so,
|> > could you please show me how having ostream::operator<< virtual would
|> > change anything. (The only ostream::operator<< that my operator<<
|> > ever calls is `ostream( ostream& , char const* )', to output the
|> > strings representing the enum's, and `ostream( ostream& , char )' for
|> > the separators.)
|> Yes James, I think we are having a failure to communicate.
|> The idea of the NetStream class is to _encapsulate_ network protocols
|> in a class that can be used _exactly_ like any C++ stream. That requires
|> not only knowledge of the transfer protocols, which can be added easily
|> to a streambuf derived class, but also the ability to convert to and
|> from a machine independent format, like XDR for ex. This second ability
|> cannot be incorporated into a streambuf class because all the _type
|> information_ is lost by then.
I'll buy that. I have generally implemented my streaming classes using
operator<< and operator>>, so that they resemble iostream. On the other
hand, they don't derive from iostream, and yes, it was necessary to
provide an operator<< and an operator>> for each type.
I agree that it would have been nice had this not been the case, but at
least in my case, having operator>> and operator<< virtual and deriving
from istream and ostream would not have helped.
|> Type information is available to the compiler. I think it would be
|> very useful if I didn't have to call XDR routines every time I send
|> data over the network. I could put those calls into the proper
|> << or >> operator if they were virtual. This would have an added
|> benefit in that the correct operators would be called in any class
|> that has defined its own << and >>, and has used << and >> to implement
|> them.
The problem is that the user has implemented his own >> and << under
certain suppositions, mainly that he is generating/parsing ASCII (or
another character code) text. There is a definite possiblity that what
he has done will *not* be appropriate if this is not the case.
|> Any object that does its own formatting, like the one you describe,
|> is on its own unless char's have the same rep. on all the machines.
|> But quite honestly, this is the first time I've heard of using
|> ostream::putchar in << and >> formatting operators, rather than
|> just using << and >>, so I think that such objects would be in the
|> minority.
I think it depends on the application. If most of your objects consist
of numeric values, then, yes, they will use formatted input and output
for these values. In my applications, numeric values are rather the
exception; most of the data is either strings or enum's.
Since I am (in principle) outputting for human consumption, I generally
have to introduce separators between the strings, and output the enum's
symbolically. The latter is particularly inadapted for network
transmission.
And of course, the problem of character representation simply isn't one.
Since the output is totally ASCII (that *is* the definition of formatted
output), I suppose that the system will ensure that it is transcoded
into/out of the same code generate by the compiler.
|> By deriving from ostream and overriding a virtual << and >>, a class
|> does need to know that NetStream exist, the same way it can't
|> distinguish between an fstream, strstream or stringstream. Deriving
|> NetStream as a parallel class requires that objects know that
|> NetStream exists, which I consider _network awareness_, and an
|> unneccessary violation of encapsulation and data hiding.
This is where we disagree. I do not think it possible for an object to
generate an adequate format for a network without being network aware.
|> I have no argument that transmitting enums as symbolic data cannot be
|> made more efficient w/o knowing that you want to make it efficient,
|> but that still doesn't mean that such a class wouldn't be useful.
|> It is true that I could just send character data over the network
|> through the streambuf subclass, but that would be an unneccassary
|> and inelegant waste of resources.
Agreed. Which is why my case with enum's requires special handling.
(If you think transmitting an int as ASCII is inefficient, imagine an
enum with perhaps eight different values, each of whose name is 20
characters long.)
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
--Beratung in industrieller Datenverarbeitung
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/12 Raw View
According to Tony Cook <tony@online.tmx.com.au>:
> The problem is that extractors are often _much_ more complex than
> inserters, for example an inserter for complex might just be:
> ostream &operator <<(ostream &os, complex v)
> {
> return os << '(' << v.r << ',' << v.i << ')';
> }
>
> while an extractor might want to match any of the following:
> <float> // just a real
> <float>'i' // just imaginary
> <float>'+'<float>'i' // fully complex
> <float>'i+'<float> // and again - not as likely
> '('<float>')' // just a real
> '(,'<float>')' // imaginary
> '('<float>','<float>')' // complex
>
> ...and imagine what might be required for inserters and extractors
> for dates.
>
> So we have inserters that stream out - assuming formatted output and
> the extract that streams it back in. I find it hard to beleive that
> the NetStream binary extractor will work any way reliably as a fully
> general formatted extractor.
Why not?
If you can write an extractor for a file then that same extractor will
work for a NetStream. Show me an example of an extractor for complex
that will not.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/12 Raw View
According to J. Kanze <kanze@gabi-soft.fr>:
> Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
> |> By deriving from ostream and overriding a virtual << and >>, a class
> |> does need to know that NetStream exist, the same way it can't
> |> distinguish between an fstream, strstream or stringstream. Deriving
> |> NetStream as a parallel class requires that objects know that
> |> NetStream exists, which I consider _network awareness_, and an
> |> unneccessary violation of encapsulation and data hiding.
>
> This is where we disagree. I do not think it possible for an object to
> generate an adequate format for a network without being network aware.
^^^^^^^^
Yes James, this is where we disagree. IMHO there is a significant
difference between _adequate_ and _optimum_. Any class should be
capable of outputting an adequate format, even if it sends all
character data. Of course, this may not be optimum. However, a
NetStream class would cover both cases sufficiently.
An object that does output only char data will still work, just not as
efficiently as one that outputs numeric data. Yet this case is no worse
than the case of just overloading streambuf and sending only char data.
In other words, the worst case for the NetStream class is the same as
the best case for only a NetBuf class, so why not add the functionality?
I think the requirement of network awareness is a serious limitation
to a NetStream class. A class is not required to be unaware of NetStream,
but neither should it be required to be aware of it either. A network
socket _IS-A_ C++ data stream, and so should be implemented as such.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/09 Raw View
According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
> We don't seem to be communicating very well. Perhaps I misunderstand
> your NetStream, or perhaps I have not really explained myself clearly.
>
> I am supposing that your NetStream data ends up on something like a
> socket, or a serial link between two processors. I am also supposing
> that for bandwidth reasons, you do not want an ASCII representation
> (otherwise, why bother with any special formatting).
>
> Now, I consider objects typical of those I write. For the most part,
> they have an operator<< (provided by me). For the most part, they
> contain enum's. The operator<< outputs an ASCII (symbolic)
> representation of the enum value, typically about 8 bytes. For
> outputting to a socket or stream where bandwidth is a consideration, I
> would not consider this an acceptable representation; I would normally
> only output a single byte with the binary internal representation.
>
> Also, since the length of the ASCII representations is variable, an
> object which contains several such enum's will output a separator
> between each one. When outputting to a stream/socket, such a
> separator is not necessary.
>
> Does this correspond to your application? If not, could you please
> indicate to me where I have misunderstood the application. If so,
> could you please show me how having ostream::operator<< virtual would
> change anything. (The only ostream::operator<< that my operator<<
> ever calls is `ostream( ostream& , char const* )', to output the
> strings representing the enum's, and `ostream( ostream& , char )' for
> the separators.)
Yes James, I think we are having a failure to communicate.
The idea of the NetStream class is to _encapsulate_ network protocols
in a class that can be used _exactly_ like any C++ stream. That requires
not only knowledge of the transfer protocols, which can be added easily
to a streambuf derived class, but also the ability to convert to and
from a machine independent format, like XDR for ex. This second ability
cannot be incorporated into a streambuf class because all the _type
information_ is lost by then.
Type information is available to the compiler. I think it would be
very useful if I didn't have to call XDR routines every time I send
data over the network. I could put those calls into the proper
<< or >> operator if they were virtual. This would have an added
benefit in that the correct operators would be called in any class
that has defined its own << and >>, and has used << and >> to implement
them.
Any object that does its own formatting, like the one you describe,
is on its own unless char's have the same rep. on all the machines.
But quite honestly, this is the first time I've heard of using
ostream::putchar in << and >> formatting operators, rather than
just using << and >>, so I think that such objects would be in the
minority.
By deriving from ostream and overriding a virtual << and >>, a class
does need to know that NetStream exist, the same way it can't
distinguish between an fstream, strstream or stringstream. Deriving
NetStream as a parallel class requires that objects know that
NetStream exists, which I consider _network awareness_, and an
unneccessary violation of encapsulation and data hiding.
I have no argument that transmitting enums as symbolic data cannot be
made more efficient w/o knowing that you want to make it efficient,
but that still doesn't mean that such a class wouldn't be useful.
It is true that I could just send character data over the network
through the streambuf subclass, but that would be an unneccassary
and inelegant waste of resources.
Pete
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/08 Raw View
In article <D9t3ps.CB9@info.physics.utoronto.ca>
peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
|> According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
|> >
|> > I guess it depends on what you are doing, but most of my operator<<'s
|> > only use ostream::put, and insert characters one at a time. They do
|> > real format conversion, at least most of the time.
|> James, I'ld like to see an example. I have trouble seeing how doing
|> your own conversion, instead of using conversion operators already
|> written and debugged for you, is not a waste of time.
The only conversion operators that I have written and debugged are for
the built-in types, and treat the built-in types as numeric values.
A significant number of my classes contain no numeric data.
A standard procedure is to use the internal, numeric representation as
an index into a table of strings.
When outputting such values to a stream or a persistency file, I just
write the binary data directly (with adjustments for the various
representations and byte orderings). This results in a much more
compact format.
|> > Even classical examples, like complex, which do use formatted output,
|> > may not do what you want. For example, complex will typically output
|> > something like `(r,i)', where r and i are output using formatted
|> > output as doubles.
|> >
|> > Would such an insertor do what you want for the NetStream? Does your
|> > NetStream really want an ASCII '(', its own representation of double,
|> > and ASCII ',', its own representation of double, and finally and ASCII
|> > ')'? I seriously doubt it.
|> ^^^^^^^^^^^^^^^^^^^^^
|> As a matter of fact James, my NetStream class couldn't care less what it
|> is that you stream out, as long as it can stream itself back in.
|> If you have a complex class that outputs itself as '(r,i)', then I assume
|> that your overloaded extractors know that and will ignore the appropriate
|> characters when it reads from the stream. Otherwise, how does a complex
|> class read itself from a file?
|> The idea is to make the NetStream class act _exactly_ like a regular C++
|> stream. Therefore _any_ class that is aware of streams would by default
|> be aware of networks.
What you are describing above is exactly the formatting capacity of
istream/ostream. What I am having trouble understanding is this: you
want to override the formatting for int and double, presumably because
this formatting is not appropriate for your stream class. But you
want to use the standard formatting for user designed classes. How
can the standard formatting for the base classes be inappropriate, but
that for the user designed classes somehow be appropriate?
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/08 Raw View
According to Stephen Williams <steve@spokane.ia-us.com>:
> In article <D9rKD1.51y@info.physics.utoronto.ca> peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
>
>
> Any third party object that defines operator<<(ostream&, object&)
> using << with for each of its members would call the correct
> netstream operator.
>
> [...]
>
> ostream& operator << (ostream& out, X& x)
> {
> out << x.i; // If out is a netstream, then netstream's operator<< would
> out << x.c; // be called for each of these, iff << were virtual.
> out << x.j; // Therefore all of the members would be formatted correctly.
>
> return out;
> }
>
>
> Negative. 'out << x.i' will call operator<<(ostream&, int). Function
^^^^^^^^
> parameters are typed statically, and that is that.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sorry Stephen, this is just not true. If it were then polymorphism
wouldn't work.
If I pass a derived class to a function expecting a base class, then
any virtual functions that are overriden in the derived class will be
called instead of the base classes version. This is C++'s version of
_run-time binding_.
The problem with trying this for the << and >> operators is that they're
not declared _virtual_ in the language definition. Therefore, binding
occurs at compile time. Changing the << and >> to virtual is what this
whole thread is about (either that or finding an appropriate work around).
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/08 Raw View
According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
> In article <D9t3ps.CB9@info.physics.utoronto.ca>
> A standard procedure is to use the internal, numeric representation as
> an index into a table of strings.
>
> When outputting such values to a stream or a persistency file, I just
> write the binary data directly (with adjustments for the various
> representations and byte orderings). This results in a much more
> compact format.
Well then James, I would suggest that what you want is
ofstream& operator <<(ofstream&, object&);
because you probably wont want to send binary data to cout, which
would be possible otherwise.
>
> |> > Even classical examples, like complex, which do use formatted output,
> |> > may not do what you want. For example, complex will typically output
> |> > something like `(r,i)', where r and i are output using formatted
> |> > output as doubles.
> |> >
> |> > Would such an insertor do what you want for the NetStream? Does your
> |> > NetStream really want an ASCII '(', its own representation of double,
> |> > and ASCII ',', its own representation of double, and finally and ASCII
> |> > ')'? I seriously doubt it.
> |> ^^^^^^^^^^^^^^^^^^^^^
>
> |> As a matter of fact James, my NetStream class couldn't care less what it
> |> is that you stream out, as long as it can stream itself back in.
>
> |> If you have a complex class that outputs itself as '(r,i)', then I assume
> |> that your overloaded extractors know that and will ignore the appropriate
> |> characters when it reads from the stream. Otherwise, how does a complex
> |> class read itself from a file?
>
> |> The idea is to make the NetStream class act _exactly_ like a regular C++
> |> stream. Therefore _any_ class that is aware of streams would by default
> |> be aware of networks.
>
> What you are describing above is exactly the formatting capacity of
> istream/ostream. What I am having trouble understanding is this: you
> want to override the formatting for int and double, presumably because
> this formatting is not appropriate for your stream class. But you
> want to use the standard formatting for user designed classes. How
> can the standard formatting for the base classes be inappropriate, but
> that for the user designed classes somehow be appropriate?
James, the point is that I am sending data in a _network_ format
(eg. XDR). If << and >> were virtual, then I could override them
for the built-in types and then classes would take care of themselves
through _polymorphism_.
As long as the class uses << or >> to stream out/in their data then
_polymorphism_ will ensure that the NetStream version of << or >> will
get called, rather than the iostream version.
Pete
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/09 Raw View
In article <D9v27n.69y@info.physics.utoronto.ca>
peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
|> According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
|> > In article <D9t3ps.CB9@info.physics.utoronto.ca>
|> > A standard procedure is to use the internal, numeric representation as
|> > an index into a table of strings.
|> >
|> > When outputting such values to a stream or a persistency file, I just
|> > write the binary data directly (with adjustments for the various
|> > representations and byte orderings). This results in a much more
|> > compact format.
|> Well then James, I would suggest that what you want is
|> ofstream& operator <<(ofstream&, object&);
|> because you probably wont want to send binary data to cout, which
|> would be possible otherwise.
You can never send binary data to cout, period. Cout is, by
definition, opened in text mode. On systems such as Unix, where there
is no distinction between text mode and binary mode, it is still
generally not a good idea to do so. Cout generally ends up either on
the screen, or in a pipe to another process expecting ASCII data.
This is the general convention. People expect processes to work this
way.
|> > |> > Even classical examples, like complex, which do use formatted output,
|> > |> > may not do what you want. For example, complex will typically output
|> > |> > something like `(r,i)', where r and i are output using formatted
|> > |> > output as doubles.
|> > |> >
|> > |> > Would such an insertor do what you want for the NetStream? Does your
|> > |> > NetStream really want an ASCII '(', its own representation of double,
|> > |> > and ASCII ',', its own representation of double, and finally and ASCII
|> > |> > ')'? I seriously doubt it.
|> > |> ^^^^^^^^^^^^^^^^^^^^^
|> >
|> > |> As a matter of fact James, my NetStream class couldn't care less what it
|> > |> is that you stream out, as long as it can stream itself back in.
|> >
|> > |> If you have a complex class that outputs itself as '(r,i)', then I assume
|> > |> that your overloaded extractors know that and will ignore the appropriate
|> > |> characters when it reads from the stream. Otherwise, how does a complex
|> > |> class read itself from a file?
|> >
|> > |> The idea is to make the NetStream class act _exactly_ like a regular C++
|> > |> stream. Therefore _any_ class that is aware of streams would by default
|> > |> be aware of networks.
|> >
|> > What you are describing above is exactly the formatting capacity of
|> > istream/ostream. What I am having trouble understanding is this: you
|> > want to override the formatting for int and double, presumably because
|> > this formatting is not appropriate for your stream class. But you
|> > want to use the standard formatting for user designed classes. How
|> > can the standard formatting for the base classes be inappropriate, but
|> > that for the user designed classes somehow be appropriate?
|> James, the point is that I am sending data in a _network_ format
|> (eg. XDR). If << and >> were virtual, then I could override them
|> for the built-in types and then classes would take care of themselves
|> through _polymorphism_.
|> As long as the class uses << or >> to stream out/in their data then
|> _polymorphism_ will ensure that the NetStream version of << or >> will
|> get called, rather than the iostream version.
We don't seem to be communicating very well. Perhaps I misunderstand
your NetStream, or perhaps I have not really explained myself clearly.
I am supposing that your NetStream data ends up on something like a
socket, or a serial link between two processors. I am also supposing
that for bandwidth reasons, you do not want an ASCII representation
(otherwise, why bother with any special formatting).
Now, I consider objects typical of those I write. For the most part,
they have an operator<< (provided by me). For the most part, they
contain enum's. The operator<< outputs an ASCII (symbolic)
representation of the enum value, typically about 8 bytes. For
outputting to a socket or stream where bandwidth is a consideration, I
would not consider this an acceptable representation; I would normally
only output a single byte with the binary internal representation.
Also, since the length of the ASCII representations is variable, an
object which contains several such enum's will output a separator
between each one. When outputting to a stream/socket, such a
separator is not necessary.
Does this correspond to your application? If not, could you please
indicate to me where I have misunderstood the application. If so,
could you please show me how having ostream::operator<< virtual would
change anything. (The only ostream::operator<< that my operator<<
ever calls is `ostream( ostream& , char const* )', to output the
strings representing the enum's, and `ostream( ostream& , char )' for
the separators.)
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/07 Raw View
In article <D9rKD1.51y@info.physics.utoronto.ca>
peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
|> According to J. Kanze <kanze@gabi-soft.fr>:
|> > Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
|> > |> If I do that then I can no longer use the overloaded inserters and
|> > |> extractors defined for third party classes. For example, operator
|> > |> << (ostream&, object&) will not accept any stream derived from ios
|> > |> (otherwise it would accept an istream).
|> >
|> > Correct. But as you pointed out in your previous posting, the format
|> > conversion for int (in ostream) is not correct for your NetStream. What
|> > is the probability that the operator<<( ostream& , object& ) does the
|> > correct format conversion for NetStream?
|> >
|> > Practically, since you need a different set of format conversions, you
|> > *will* have to provide a conversion function for each class.
|> Any third party object that defines operator<<(ostream&, object&)
|> using << with for each of its members would call the correct
|> netstream operator. For ex.,
|> class X {
|> int i;
|> char c[10];
|> float j;
|> public:
|> friend ostream& operator <<(ostream&, X&);
|> };
|> ostream& operator << (ostream& out, X& x)
|> {
|> out << x.i; // If out is a netstream, then netstream's operator<< would
|> out << x.c; // be called for each of these, iff << were virtual.
|> out << x.j; // Therefore all of the members would be formatted correctly.
|> return out;
|> }
|> Of course, if X's << used binary op's like write() all bets would be off,
|> but since out could be user output (eg., cout) then using binary op's
|> in << would not be likely (i.e., smart).
I guess it depends on what you are doing, but most of my operator<<'s
only use ostream::put, and insert characters one at a time. They do
real format conversion, at least most of the time.
Even classical examples, like complex, which do use formatted output,
may not do what you want. For example, complex will typically output
something like `(r,i)', where r and i are output using formatted
output as doubles.
Would such an insertor do what you want for the NetStream? Does your
NetStream really want an ASCII '(', its own representation of double,
and ASCII ',', its own representation of double, and finally and ASCII
')'? I seriously doubt it.
|> Since this is a netstream, ostream's formatting flags would be meaningless,
|> but they're easy enough to ignore.
|> Why are people having such a hard time accepting that this is not a
|> stupid idea? (No offence James.:)
Maybe because we've already tried it, and found that it didn't
work:-).
Pretend that ostream *did* have virtual operator<<'s, take a couple of
user defined operator<<'s, and execute them mentally to see what the
output is. In my experience, it typically *won't* be what you need.
It is a sad fact of C++ life that if an object is not NetStream aware,
it cannot convert itself into a NetStream by some form of magic.
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/07 Raw View
According to James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>:
>
> I guess it depends on what you are doing, but most of my operator<<'s
> only use ostream::put, and insert characters one at a time. They do
> real format conversion, at least most of the time.
>
James, I'ld like to see an example. I have trouble seeing how doing
your own conversion, instead of using conversion operators already
written and debugged for you, is not a waste of time.
> Even classical examples, like complex, which do use formatted output,
> may not do what you want. For example, complex will typically output
> something like `(r,i)', where r and i are output using formatted
> output as doubles.
>
> Would such an insertor do what you want for the NetStream? Does your
> NetStream really want an ASCII '(', its own representation of double,
> and ASCII ',', its own representation of double, and finally and ASCII
> ')'? I seriously doubt it.
^^^^^^^^^^^^^^^^^^^^^
As a matter of fact James, my NetStream class couldn't care less what it
is that you stream out, as long as it can stream itself back in.
If you have a complex class that outputs itself as '(r,i)', then I assume
that your overloaded extractors know that and will ignore the appropriate
characters when it reads from the stream. Otherwise, how does a complex
class read itself from a file?
The idea is to make the NetStream class act _exactly_ like a regular C++
stream. Therefore _any_ class that is aware of streams would by default
be aware of networks.
Pete
Author: steve@spokane.ia-us.com (Stephen Williams)
Date: 1995/06/07 Raw View
In article <D9rKD1.51y@info.physics.utoronto.ca> peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
Any third party object that defines operator<<(ostream&, object&)
using << with for each of its members would call the correct
netstream operator.
[...]
ostream& operator << (ostream& out, X& x)
{
out << x.i; // If out is a netstream, then netstream's operator<< would
out << x.c; // be called for each of these, iff << were virtual.
out << x.j; // Therefore all of the members would be formatted correctly.
return out;
}
Negative. 'out << x.i' will call operator<<(ostream&, int). Function
parameters are typed statically, and that is that.
The only hook into the output produced by this vendor supplied
(compiled and linked) operator<< is at the streambuf, which is after
the formatting has taken place.
I believe that the original idea of writing a NetStream and having it
magically override the formatting the core types is impossible in C++
as we know it. The provider of NetStream will be forced to create a
different class and supply all the needed operator<< and operator>>
functions needed.
I've been through similar soul-searching myself.
--
Stephen 2. Williams
steve@icarus.com
Fight License Managers! Buy from
vendors who use honor system!
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/05 Raw View
According to Paul J. Ste. Marie <pstemari@erinet.com>:
> In article <D9Jw2w.Moq@info.physics.utoronto.ca>,
> peter@chinook.physics.utoronto.ca (Peter Berdeklis) wrote:
> :[snip]
> :
> :Is there any way to do it without virtual >> and <<?
> :
>
> Inherit from ios instead of from istream and ostream. Inheriting
> from istream and ostream isn't really correct here, since you are
> changing definitions and not simply extending behavior. You can
> continue to use the streambuf hierarchy as appropriate.
If I do that then I can no longer use the overloaded inserters and
extractors defined for third party classes. For example, operator
<< (ostream&, object&) will not accept any stream derived from ios
(otherwise it would accept an istream).
In fact, any time you have virtual functions you are allowed to
change the behaviour of an operation. That's the whole point of
virtual functions. In this case, instead of having the >> and <<
operators convert to and from character data, I want them to
convert to and from network data. I don't see why that would be
incorrect.
Pete
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/06 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
|> According to Paul J. Ste. Marie <pstemari@erinet.com>:
|> > In article <D9Jw2w.Moq@info.physics.utoronto.ca>,
|> > peter@chinook.physics.utoronto.ca (Peter Berdeklis) wrote:
|> > :[snip]
|> > :
|> > :Is there any way to do it without virtual >> and <<?
|> > :
|> >
|> > Inherit from ios instead of from istream and ostream. Inheriting
|> > from istream and ostream isn't really correct here, since you are
|> > changing definitions and not simply extending behavior. You can
|> > continue to use the streambuf hierarchy as appropriate.
|> If I do that then I can no longer use the overloaded inserters and
|> extractors defined for third party classes. For example, operator
|> << (ostream&, object&) will not accept any stream derived from ios
|> (otherwise it would accept an istream).
Correct. But as you pointed out in your previous posting, the format
conversion for int (in ostream) is not correct for your NetStream. What
is the probability that the operator<<( ostream& , object& ) does the
correct format conversion for NetStream?
Practically, since you need a different set of format conversions, you
*will* have to provide a conversion function for each class.
|> In fact, any time you have virtual functions you are allowed to
|> change the behaviour of an operation. That's the whole point of
|> virtual functions. In this case, instead of having the >> and <<
|> operators convert to and from character data, I want them to
|> convert to and from network data. I don't see why that would be
|> incorrect.
Only because there will be formatting functions for third party classes
which *will* convert to an from character data, *if* you allow it by
deriving from ostream.
Whether you want to derive from ios or not, I don't know. Does the ios
formatting and state information correspond to something equivalant in
your NetStream. If not, you will probably want to create a new base
class from scratch, too (to hold the pointer to the streambuf).
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
--Beratung in industrieller Datenverarbeitung
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/06 Raw View
According to J. Kanze <kanze@gabi-soft.fr>:
> Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
> |> If I do that then I can no longer use the overloaded inserters and
> |> extractors defined for third party classes. For example, operator
> |> << (ostream&, object&) will not accept any stream derived from ios
> |> (otherwise it would accept an istream).
>
> Correct. But as you pointed out in your previous posting, the format
> conversion for int (in ostream) is not correct for your NetStream. What
> is the probability that the operator<<( ostream& , object& ) does the
> correct format conversion for NetStream?
>
> Practically, since you need a different set of format conversions, you
> *will* have to provide a conversion function for each class.
Any third party object that defines operator<<(ostream&, object&)
using << with for each of its members would call the correct
netstream operator. For ex.,
class X {
int i;
char c[10];
float j;
public:
friend ostream& operator <<(ostream&, X&);
};
ostream& operator << (ostream& out, X& x)
{
out << x.i; // If out is a netstream, then netstream's operator<< would
out << x.c; // be called for each of these, iff << were virtual.
out << x.j; // Therefore all of the members would be formatted correctly.
return out;
}
Of course, if X's << used binary op's like write() all bets would be off,
but since out could be user output (eg., cout) then using binary op's
in << would not be likely (i.e., smart).
Since this is a netstream, ostream's formatting flags would be meaningless,
but they're easy enough to ignore.
Why are people having such a hard time accepting that this is not a
stupid idea? (No offence James.:)
Pete
Author: pstemari@erinet.com (Paul J. Ste. Marie)
Date: 1995/06/04 Raw View
In article <D9Jw2w.Moq@info.physics.utoronto.ca>,
peter@chinook.physics.utoronto.ca (Peter Berdeklis) wrote:
:[snip]
:
:Is there any way to do it without virtual >> and <<?
:
Inherit from ios instead of from istream and ostream. Inheriting
from istream and ostream isn't really correct here, since you are
changing definitions and not simply extending behavior. You can
continue to use the streambuf hierarchy as appropriate.
--Paul J. Ste. Marie, pstemari@well.sf.ca.us, pstemari@erinet.com
The Financial Crimes Enforcement Network claims that they capture every
public posting that has their name ("FinCEN") in it. I wish them good hunting.
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/01 Raw View
In article H70@info.physics.utoronto.ca, peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
>First, as always, thank you to those who have answered.
>
>However, the answers I've gotten basically have said that the
>iostream classes are meant for formatted output, and so not
>appropriate for the job. This is only partially true. The
>stream classes can do binary output if you initiate them in
>ios::binary mode (now part of the WP, I believe). In this
>mode, basic data types are saved in their native representation,
>not as character data.
This interpretation is not correct.
IOstreams uses the same file model as C stdio: A file is a sequence of
bytes. Just like C stdio, a file may be opened in either text mode
or binary mode. Exactly what that means depends on the operating system.
More about that in a moment.
As with C stdio, you can dump data directly into or from a file with
no conversion, or you can convert between text format and internal format.
With C stdio, you use the fread and fwrite function for no conversion,
printf and scanf for text conversion. With IOStreams you use read and
write member functions for no conversion, inserters and extractors
(<< and >>) for text conversion.
Example: If an int variable contains the value 31, you can write a word
containing a binary value 31 (000...00011111) by using fwrite or write.
You can also convert that value to two text characters, '3' and '1' in
decimal representation, or perhaps two text characters '1' and 'F' in
hex, or octal characters, or whatever, using either printf or
an insertion operator. This is the "text conversion" question.
The C and C++ file model is (not by coincidence) the same as the Unix
file model. On Unix there is only one kind of file. It may contain
text or binary data. Other operating systems have different kinds of
files. The physical format is different, and often different sets of
commands are required to access different file types. Typically, a
text file is presumed to contain text, and a binary file contains
binary data. Further specialization is possible, even common, but C and
C++ do not make further distinctions.
The C and C++ model of a text file is a sequence of lines, each line
consisting of text characters and terminated with a newline character.
The I/O library functions do whatever is necessary to convert between
the program model of a text file and the file representation as
seen by the operating system, which is typically different. This is the
"file access" question.
You can read and write binary information to a text file, or text information
to a binary file, but you cannot always depend on the results to be what
you want. For example, if you write a binary character with the value 10
to an MSDOS text file, the library functions will interpret it as a newline
character, and insert a CR character ahead of it. If you write a line of
text including a newline to an MSDOS binary file, it won't get the CR
character inserted that it otherwise would.
You get the best and most portable results if you read or write binary
information using a file opened in binary mode, and text information
with a (different) file opened in text mode.
---
Steve Clamage, stephen.clamage@eng.sun.com
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/02 Raw View
According to Steve Clamage <clamage@Eng.Sun.COM>:
> In article H70@info.physics.utoronto.ca, peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
[snip all of a long article straightening me out about
binary and text files]
Sorry about my misinterpretation. I try to avoid such blunders
on the net (although they're quite frequent in person :-).
Thanks for response.
However, your response only changes my interpretation of the problem,
not my prefered solution. (Please understand, this is a real problem
and not a thought experiment to discuss virtual >> and <<.)
As you said, the >> and << operators effectively "translate" the C and
C++ view (definition?) of files to that of the current OS. You could
similarly say that my NetStream inserters and extractors translate
the C and C++ view of data to that of the current network protocol,
of which the base iostreams are not aware.
In other words, whereas the regular insterter might convert the integer
31 to the characters "3" and "1", my NetStream inserter would translate
the integer to the appropriate network representation. The opposite is
true for the NetStream extractor. This still seems like the best way
to do this.
Is there any way to do it without virtual >> and <<?
Pete
Author: freyburg@glitch.stanford.edu (Brian Michael Freyburger)
Date: 1995/06/02 Raw View
I think the proper way to do this is to write a new streambuf which
sends the characters over a network. The appropriate operators in a
streambuf are all virtual, in fact, this is how fstream and strstream
are implemented. I believe the library was designed this way so that
you can simply reimplement a few streambuf operations (xsgetn, xsputn,
underflow, overflow, etc.), rather than all the formatted/unformatted
operations. If you want to convert the data to a different format
(convert it/pad it/etc.), you can do this before it is actually sent
over the network.
Assuming you write such a "NetStreambuf", your NetStream object could
then simply be:
struct NetStream : public ostream
{
NetStream() : ostream(new NetStreambuf)
{}
};
Of course, you probably want more complicated
constructors/destructors, etc.
Hope this helps,
Brian Freyburger <freyburg@cs.stanford.edu>
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/01 Raw View
In article <D9G9Bz.ALG@info.physics.utoronto.ca>
peter@chinook.physics.utoronto.ca (Peter Berdeklis) writes:
|> I have been thinking about writing a NetStream class, derived
|> from iostream. Of course, I have to also create a NetBuf class,
|> derived from streambuf, which fills and empty's the buffer
|> through network calls, but that's not my problem.
|> I would prefer to send binary data for effeciency (a float
|> may be 4 bytes binary but 15 char bytes). Obviously, I need
|> to convert the representations from the local rep. to network
|> rep. and back, probably using hton and ntoh functions.
|> Here's my problem.
|> The type data is used by the compiler to call the appropriate
|> overloaded operator. Great! I can create an operator <<(int)
|> for my NetStream class which calls the appropriate hton func.
|> and passes the result to iostream <<(int), for ex.
|> Now what happens when I try to pass an object to my NetStream?
|> Assuming my object has defined it's own operator <<(ostream&, object&),
|> because the operator<< is not virtual, my NetStream gets bypassed!
|> Do I have to create an operator <<(NetStream&, object&) for every
|> object I pass over the net?
Yes. If you think about it, this should be obvious. Operator<<(
ostream& ... formats things in one way, operator<<( Netstream&
... expects a different formatting. Who's going to do it if you
don't?
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/01 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: I have been thinking about writing a NetStream class, derived
: from iostream. Of course, I have to also create a NetBuf class,
: derived from streambuf, which fills and empty's the buffer
: through network calls, but that's not my problem.
: I would prefer to send binary data for effeciency (a float
: may be 4 bytes binary but 15 char bytes). Obviously, I need
: to convert the representations from the local rep. to network
: rep. and back, probably using hton and ntoh functions.
: Here's my problem.
: The type data is used by the compiler to call the appropriate
: overloaded operator. Great! I can create an operator <<(int)
: for my NetStream class which calls the appropriate hton func.
: and passes the result to iostream <<(int), for ex.
Hmm. I suspect you're trying to use the wrong tool for the job.
The IOStreams library (istream, ostream and base classes) are
designed for formatted I/O - trying to use them for binary output is
probably the wrong thing to do.
Instead, create a parallel hierarchy - one that still uses streambuf
and it's derived classes, as these do no formatting on the data -
that is designed for binary I/O.
For example if the output stream were 'obstream', you would define
inserters like:
obstream &operator <<(obstream &out, const T&object);
and extractors like:
ibstream &operator >>(ibstream &in, T&object);
which could be used in substantially the same way as IOStreams
inserters and extractors.
: Now what happens when I try to pass an object to my NetStream?
: Assuming my object has defined it's own operator <<(ostream&, object&),
: because the operator<< is not virtual, my NetStream gets bypassed!
By using a separate hierarchy you will get a compile time error when
you try to insert the object, IMHO much better than the run-time
mess that you'll get if you try to use ostream and istream classes.
: Do I have to create an operator <<(NetStream&, object&) for every
: object I pass over the net? This is a definite problem if I try
: to pass objects I didn't create, since I don't know what is done
: in its operator <<(ostream&, object&).
That's right - you don't. And the other very real problem is that
an inserter [operator <<(ostream &, T)] is designed to produce
'pretty output' - not easily machine readable output.
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
Author: jonathan@cae.ca (Jonathan Hutchinson)
Date: 1995/06/01 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: I have been thinking about writing a NetStream class, derived
: from iostream. Of course, I have to also create a NetBuf class,
: derived from streambuf, which fills and empty's the buffer
: through network calls, but that's not my problem.
: I would prefer to send binary data for effeciency (a float
: may be 4 bytes binary but 15 char bytes). Obviously, I need
: to convert the representations from the local rep. to network
: rep. and back, probably using hton and ntoh functions.
: Here's my problem.
: The type data is used by the compiler to call the appropriate
: overloaded operator. Great! I can create an operator <<(int)
: for my NetStream class which calls the appropriate hton func.
: and passes the result to iostream <<(int), for ex.
: Now what happens when I try to pass an object to my NetStream?
: Assuming my object has defined it's own operator <<(ostream&, object&),
: because the operator<< is not virtual, my NetStream gets bypassed!
: Do I have to create an operator <<(NetStream&, object&) for every
: object I pass over the net? This is a definite problem if I try
: to pass objects I didn't create, since I don't know what is done
: in its operator <<(ostream&, object&).
: Is there any solution to this?
I may be a little of track here, but could you not write your <<()
operator to call a virtual member function of your class? Then the
member function being called may be overloaded by derived classes.
: Thanks for your time.
: Pete
Jonathan Hutchinson
jonathan@cae.ca
Author: immel@fenway.centerline.com (Mark Immel)
Date: 1995/06/01 Raw View
I'm not sure quite what the problem is here. Presumably, there's a
function
ostream& operator<<(ostream& stream, object& obj)
for some type "object".
It's body uses things like:
stream << obj.i << endl;
What's obj.i? If it's a primitive datatype, you're all set, since
you've provided clever versions of operator<<() for primitive
datatypes on NetStreams. If it's not a builtin type, the same
argument applies by induction.
--
Mark Immel
immel@centerline.com
(617) 498-3409
In article <1995Jun1.161559.20537@cae.ca> jonathan@cae.ca (Jonathan Hutchinson) writes:
Newsgroups: comp.std.c++
Path: wcap.centerline.com!news3.near.net!paperboy.wellfleet.com!news-feed-1.peachnet.edu!news.Gsu.EDU!gatech!newsjunkie.ans.net!Rezonet.net!nowhere!jonathan
From: jonathan@cae.ca (Jonathan Hutchinson)
Organization: CAE
X-Newsreader: TIN [version 1.2 PL2]
References: <D9G9Bz.ALG@info.physics.utoronto.ca>
Date: Thu, 1 Jun 1995 16:15:59 GMT
Lines: 41
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: I have been thinking about writing a NetStream class, derived
: from iostream. Of course, I have to also create a NetBuf class,
: derived from streambuf, which fills and empty's the buffer
: through network calls, but that's not my problem.
: I would prefer to send binary data for effeciency (a float
: may be 4 bytes binary but 15 char bytes). Obviously, I need
: to convert the representations from the local rep. to network
: rep. and back, probably using hton and ntoh functions.
: Here's my problem.
: The type data is used by the compiler to call the appropriate
: overloaded operator. Great! I can create an operator <<(int)
: for my NetStream class which calls the appropriate hton func.
: and passes the result to iostream <<(int), for ex.
: Now what happens when I try to pass an object to my NetStream?
: Assuming my object has defined it's own operator <<(ostream&, object&),
: because the operator<< is not virtual, my NetStream gets bypassed!
: Do I have to create an operator <<(NetStream&, object&) for every
: object I pass over the net? This is a definite problem if I try
: to pass objects I didn't create, since I don't know what is done
: in its operator <<(ostream&, object&).
: Is there any solution to this?
I may be a little of track here, but could you not write your <<()
operator to call a virtual member function of your class? Then the
member function being called may be overloaded by derived classes.
: Thanks for your time.
: Pete
Jonathan Hutchinson
jonathan@cae.ca
--
My opinions are not necessarily those of my employer.
Author: mlc@wup.de (Michael Lechner)
Date: 1995/06/01 Raw View
Peter Berdeklis (peter@chinook.physics.utoronto.ca) wrote:
: Here's my problem.
: The type data is used by the compiler to call the appropriate
: overloaded operator. Great! I can create an operator <<(int)
: for my NetStream class which calls the appropriate hton func.
: and passes the result to iostream <<(int), for ex.
: Now what happens when I try to pass an object to my NetStream?
: Assuming my object has defined it's own operator <<(ostream&, object&),
: because the operator<< is not virtual, my NetStream gets bypassed!
: Do I have to create an operator <<(NetStream&, object&) for every
: object I pass over the net? This is a definite problem if I try
: to pass objects I didn't create, since I don't know what is done
: in its operator <<(ostream&, object&).
That's not a problem if you have really derived from ostream.
If someone defines :
ostream &
MYCLASS::operator <<(ostream &strm, Object &obj)
{
strm << obj.myInt; // methode operator<<(int) called !
strm << whatever; // methode operator<<(XXX) called !
return strm;
}
If someone doesn't use the given ostream-object in his
methode - that's not your problem ;-)
Your stream-object is consulted!
: Is there any solution to this?
YES - It's not a problem ;-)
cu
Michael;
--
+-------------------------------+--------------------------------------+
| Michael Lechner | Wiechers & Partner Datentechnik GmbH |
| | Forschung & Entwicklung (R&D) |
| | An der alten Ziegelei 2 |
| eMail: mlc@wupmon.wup.de | D-40771 Monheim (Germany) |
+-------------------------------+--------------------------------------+
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/01 Raw View
First, as always, thank you to those who have answered.
However, the answers I've gotten basically have said that the
iostream classes are meant for formatted output, and so not
appropriate for the job. This is only partially true. The
stream classes can do binary output if you initiate them in
ios::binary mode (now part of the WP, I believe). In this
mode, basic data types are saved in their native representation,
not as character data.
My NetStream class would clearly be intended for ios::binary mode.
Secondly, the problem with creating a new class hierarcy is that
I can't always define an operator <<(NetStream &, object &).
I don't necessarily now how to "stream" a third party object, just
as I don't necessarily know how to copy it. Basically, the NetStream
operator << and >> would be used to copy objects across a network.
If I could redefine the i/ostream operators << and >>, then I could
use the third party's already defined operators to pass this object
using my NetStream class. As it is, I can't.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/01 Raw View
According to Jonathan Hutchinson <jonathan@cae.ca>:
> I may be a little of track here, but could you not write your <<()
> operator to call a virtual member function of your class? Then the
> member function being called may be overloaded by derived classes.
The problem is that the operators >> and << are not defined virtual.
For example:
class X // third party lib class
{
public:
...
friend ostream& operator << (ostream&, X&);
friend istream& operator >> (istream&, X&);
private:
...
int *something_hidden;
};
int main()
{
NetStream net;
X x;
net << x; // try to send x over the net
return 0;
}
The problem is that operator << of class X expects an ostream&,
from which NetStream is derived. However, << and >> are
not declared virtual in the standard. When NetStream gets passed
to operator <<, _ostream's_ operator << gets called not NetStream's.
Hope this clears it up.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/01 Raw View
According to Mark Immel <immel@fenway.centerline.com>:
>
> I'm not sure quite what the problem is here. Presumably, there's a
> function
>
> ostream& operator<<(ostream& stream, object& obj)
>
> for some type "object".
>
> It's body uses things like:
>
> stream << obj.i << endl;
>
> What's obj.i? If it's a primitive datatype, you're all set, since
> you've provided clever versions of operator<<() for primitive
> datatypes on NetStreams. If it's not a builtin type, the same
> argument applies by induction.
Again, because the iostream operators << and >> are not declared
virtual, NetStream's operators >> and << never get called within
obj's operator <<.
In other words, NetStream will work fine for native data types,
but not for objects, because the insertor and extractor operators
are not polymorphic.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/06/01 Raw View
According to Michael Lechner <mlc@wup.de>:
> That's not a problem if you have really derived from ostream.
>
> If someone defines :
>
> ostream &
> MYCLASS::operator <<(ostream &strm, Object &obj)
> {
> strm << obj.myInt; // methode operator<<(int) called !
> strm << whatever; // methode operator<<(XXX) called !
^^^^^^^
> return strm;
> }
>
> If someone doesn't use the given ostream-object in his
> methode - that's not your problem ;-)
Because the operator's << and >> are not virtual, strm << whatever; calls
_ostream_'s operator <<, not NetStream's. Polymorphism only exists for
virtual functions.
Pete
Author: peter@chinook.physics.utoronto.ca (Peter Berdeklis)
Date: 1995/05/31 Raw View
I have been thinking about writing a NetStream class, derived
from iostream. Of course, I have to also create a NetBuf class,
derived from streambuf, which fills and empty's the buffer
through network calls, but that's not my problem.
I would prefer to send binary data for effeciency (a float
may be 4 bytes binary but 15 char bytes). Obviously, I need
to convert the representations from the local rep. to network
rep. and back, probably using hton and ntoh functions.
Here's my problem.
The type data is used by the compiler to call the appropriate
overloaded operator. Great! I can create an operator <<(int)
for my NetStream class which calls the appropriate hton func.
and passes the result to iostream <<(int), for ex.
Now what happens when I try to pass an object to my NetStream?
Assuming my object has defined it's own operator <<(ostream&, object&),
because the operator<< is not virtual, my NetStream gets bypassed!
Do I have to create an operator <<(NetStream&, object&) for every
object I pass over the net? This is a definite problem if I try
to pass objects I didn't create, since I don't know what is done
in its operator <<(ostream&, object&).
Is there any solution to this?
(Yes, maybe I am trying to influence the committee. :-)
While I'm on the subject of iostreams, why was iostream left out
of the WP? I haven't gotten a chance to check everything, but
I'm assuming that the committee was trying to avoid multiple
inherritance. If so, why? Is there a runtime penalty for it?
(I can't see one off hand.)
Thanks for your time.
Pete