Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!elroy.jpl.nasa.gov!jarthur!dfoster From: dfoster@jarthur.Claremont.EDU (Derek R. Foster) Newsgroups: comp.lang.c++ Subject: Re: Deriving new stream types: tstream Message-ID: <10603@jarthur.Claremont.EDU> Date: 1 Feb 91 07:45:52 GMT References: Organization: Harvey Mudd College, Claremont, CA 91711 Lines: 96 In article jak@cs.brown.edu writes: >I would like to create a type which behaves precisely as does an ostream >except that the constructor would take two ostream references, and every >operation would affect both ostreams equally. ... >out how to do this right, but I thought I would first ask if anyone else >has done this, or anything similar enough to provide either a cookbook >approach or some hints on what to avoid or worry about. Well, I fought long and hard with the TC++ iostream.h header file, and I eventually gained some understanding of it, albeit sketchy in a few places. My goal was to create an ostream type that would output to the console device, like cprintf, so I could, for instance, write con << clear << fore(LIGHTGREEN) << "Green text" << back(LIGHTGRAY) << "Gray text"; I eventually succeeded in this, and although my result is more than a little shaky, (I guessed at what some of the member functions did based on their names and their return values, since TC++ thoughtfully failed to provide documentation. Sort of risky.), It seems to work fine for all the code I've tried it with. I could make this code available if anyone is interested. What you want to do is much easier. Keep this in mind: an ostream doesn't actually do output itself. Instead, it formats the output and then tells the streambuf associated with it to deal with the output. Thus, if all you want to do is create an ostream-like object to output to two different streams, you don't need to derive from ostream at all. What you need to do is create a streambuf object which will output to two destinations instead of one. Then, you could simply associate this new streambuf with a normal ostream, or, if you really want to be able to use a fancy constructor as you've described, with a class derived from ostream which simply adds the new constructor, and uses it to initialize itself as an ostream with one of your new streambufs instead the normal one it would usually get. One way would be to have your derived streambuf contain pointers to two other more normal streambufs. Then you could just define the relevant member functions of the derived streambuf to call the same functions in each of the pointed-to streambufs. (Your derived streambuf can even be unbuffered, if you like, since its buffer won't be used for anything.) I.e. to use this, you might eventually be able to do something like: #include class mystreambuf : public streambuf { streambuf * A; streambuf * B; mystreambuf(streambuf* a, streambuf* b) {A=a;B=b;unbuffered(1);); int overflow(int = EOF) {A->overflow(); B->overflow();}; // probably need to redefine all the virtual output functions, like // do_sputn() etc. in the same way. I'm not sure what to do about // return values. (Probably will have to vary with the function.) } filebuf buf1("Out1.dat"); filebuf buf2("Out2.dat"); mystreambuf x(strbuf1, strbuf2); ostream y(x); y << "Testing 1.2.3..."; If you're really serious about the constructor being a constructor from two ostreams, you might try something like: // define mystreambuf as before class tstream : public ostream { tstream(ostream& A, ostream& B) : ostream(new mystreambuf(A.rdbuf(),B.rdbuf()) {}; } ofstream file1("abc.dat"); ofstream file2("def.dat"); tstream both(file1, file2); both << "Testing 4..5..6"; note 1: A.rdbuf() is simply the value of A's pointer to the streambuf that it expects to output on. note 2: This creates a semi-permanent tie between the buffers of the two original streams and the buffer of the tstream. If you go mucking about with the buffers of the original streams, you will have an effect on the tstream. This could be good or bad depending on what you do. I hope this helps! Derek Riippa Foster