Article View: gnu.g++.help
Article #740Re: manipulators for class derived from ostream?
From: Dietmar Kuehl
Date: Wed, 23 Aug 1995 13:00
Date: Wed, 23 Aug 1995 13:00
134 lines
5594 bytes
5594 bytes
hi,
Blue Sky Tours (poet@mack.rt66.com) wrote:
> I wish to define a manipulator for a class which is derived from
> ostrstream. There does not seem to be a way to do this.
There are ways to do this (e.g. by using a dynamic_cast) but it is
likely that you don't really want to do this! You should remember that
the classes derived from ios (e.g. [io]stream, [io]strstream,
[io]fstream) are just "frontends" which provide the capability to write
"inserter" functions for user-defined types/classes. The classes
derived from [io]stream are convinience classes such that you can
easily access the underlying abstractions for streams: the classes
derived from streambuf. You can use these abstractions with just
an [io]stream. All you have to do is to create the corresponding
streambuf and use it as an argument to [io]stream.
> For example, I have the following def:
>
> class Mail : public ostrstream {
[...]
> public:
> Mail(void);
> Mail(char *to, string name);
> ~Mail();
>
> int init(char *to, string name);
> void recipient(char *to);
> void send(char *subject);
> int load_buffer(void);
> void clear(void);
> void endmsg(void);
> };
An ostream which has some input (member messages)??? This lets the
class look like an aggregate of arbitary data... But I'm not going to
discuss class design here.
> This class works just fine, but I have to explicitly call
> mail.send(), to actually have my message sent:
This is exactly what I would expect from a class representing a mail!
Only the subject as an argument irritates me: I would expect that
a mail is send with the same header and content to one or more people.
Thus I think that the recipient should be an argument to the send()
function while the rest should be constructor arguments (maybe
replaceable with some additional member functions).
> I would much rather be able to have it work like so:
>
> mail << "Hello" << send("testing");
Hm. I guess you are thinking of an analogy with the 'flush'
manipulator... This is the only manipulator (I can remember) which
doesn't modify the contents of the stream but rather forces the
underlying streambuf to synchronize the internal with the external
representation (which can indeed modify the contents of the stream). I
think there should be no send manipulator: while the semantics of
"flushing a stream" is well known prior to the existence of the flush
manipulator (and even prior to the existence of C++...) there is
normally no manipulation called send on a stream.
In my opinion you should create a class derived from streambuf (or
maybe from strstreambuf) which represents a mail. Subject and other
header stuff could be a constructor arguments. The additional data
could be accessible with some additional member functions. To use this
class conviniently there could be a class "omailstream" derived from
ostream which provides easy access. There is no need for a "send"
manipulator since it is more or less irritating! Instead there should
be a "send" member function taking the recipient as an argument.
> When I try to define a manipulator like:
>
> Mail &send(Mail &os, char *str)
[...]
> If I try to define the manipulator like:
>
> ostream &send(ostream &os, char *str)
None of these function is a manipulator! You can create a manipulator
"foo" without an argument like this:
ostream &foo(ostream &);
This doesn't work for manipulators with arguments. In these cases you
have to create a temporary object carrying the arguments (see below for
an example).
> So, how do I tell the compiler that I wish to access a variable in my
> Mail class from an ostream manipulator?
Here is finally some code which can be used to implement a
manipulator for a class derived from ostream. Note that I
wouldn't use such code myself (unless someone explains the
advantages of it...). Also, this code is "dirty" as there
is a lot of stuff missing (e.g. the send class is not "nice",
the operator<< don't uses opfx()/osfx(),...).
class send
{
friend ostream &operator<< (ostream &, send const &);
private:
char *subject;
public:
send(char *s): subject(s) {}
};
ostream &operator<< (ostream &out, send const &subject)
{
try
{
Mail &mail = dynamic_cast<Mail>out;
mail.send(subject.subject);
}
catch (...)
{
// we have a "normal" stream: ignore the send manipulator
}
return out;
}
It is likely that the dynamic_cast is not supported by your compiler.
Actually I'm not really sure that the syntax is correct since I'm not
used to the "new style" casts: I have no compiler available which
supports them. You can replace the dynamic_cast with an "old style"
cast if you really know what you are doing! Since this is code which
will be found in the interface of the class Mail it is unlikely
that you know what is happening...
dk
---
http://www.informatik.uni-konstanz.de/~kuehl
dietmar.kuehl@uni-konstanz.de
I am a realistic optimist - that's why I appear to be slightly pessimistic
Technical Details
Message-ID:
<41f8q9$c5p@eurybia.rz.uni-konstanz.de>Path:
arc1-ca.pugleaf.net!news.uni-konstanz.de!horn!kuehlReferences:
<41dfe5$9m7@mack.rt66.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!news.uni-konstanz.de!horn!kuehl From: kuehl@horn (Dietmar Kuehl) Newsgroups: gnu.g++.help,comp.lang.c++ Subject: Re: manipulators for class derived from ostream? Date: 23 Aug 1995 13:00:57 GMT Organization: Fakultät für Mathematik und Informatik Distribution: world Message-ID: <41f8q9$c5p@eurybia.rz.uni-konstanz.de> References: <41dfe5$9m7@mack.rt66.com> Reply-To: dietmar.kuehl@uni-konstanz.de NNTP-Posting-Host: horn.informatik.uni-konstanz.de X-Newsreader: TIN [version 1.1 PL6]