TITLE: outputting to 1 of N streams using streambuf (Newsgroups: comp.lang.c++, 18 Feb 97) RIDDER: Bavo De Ridder (ludwig@wina.student.kuleuven.ac.be) : A few days ago, someone had the following problem: : he wanted to write something out but it should be : possible to write to a file or an regular stream. : Should he always check a boolean and then write? : No. [snip] : I gave some thought about the problem and came : up with the following: I have written a new class : gostream (general ostream ). The only thing you have : to do is initializing it with a ostream or a ofstream. KUEHL: kuehl@horn.informatik.uni-konstanz.de (Dietmar Kuehl) Well, we already get some disagreement: For good or bad, there is actually no need to write a new class to accomplish this task. Here is corresponding sample code using a file if there is an argument naming a file: int main(int ac, char *av[]) { // First, open a file if possible: ofstream fout; if (ac > 1) out.open(av[1], ios::out); // Then, use this file if it was successful, otherwise use 'cout': ostream out(fout? fout.rdbuf(): cout.rdbuf()); // Now go ahead and write to 'out'. Nothing else has to be done! } Of course, you can encapsulate this code into a class derived from 'ostream' which merely defines a constructor and, maybe some functions special to this class like a function returning 'true' if 'cout' is used and 'false' otherwise. RIDDER: : From then on you just write to the gostream. : I also included the framework for adding manipulators. KUEHL: Hm, no, you should not do this! In fact, there is already a possibility to extend the IOStream library installed. Actually, there are even two: - You can extend the IOStream library to write or read new types, and to define manipulators modifying the behavior of the read or write operations. The interface to these extensions are the classes derived from 'ios' like 'istream' and 'ostream' (well, actually 'basic_ios', 'basic_istream', 'basic_ostream' but lets ignore templatization for this matter...). - You can extend the IOStream library to read from and write to "new external representations". Examples for this are GUI windows, automatic compression/decompression or encryption/decryption, special OS facilities like message queues, sockets, printers, etc. Yet another class of external representations are sources/destinations where the characters sent are handled in a specific way. For example, a character may be sent to multiple different destinations (e.g. to the error stream and a log file), to one out of multiple destinations depending on the setting of some flags, be capitalized (or lowered) before being sent to some destination etc. Extensions like this are implemented at a different layer, namely by deriving from the class 'streambuf'. I will give some information on how the latter can be achived (there are already sufficient examples of the former...). Basically, a 'streambuf' is an abstraction from a buffered sequence. It allows the user to write special function to obtain the next character(s) for the buffer. This is done by overriding the function 'overflow()' and 'underflow()' which are called if the buffer exceeded when writing or is empty when reading, respectively. The advantage of this approach is that you don't have to know in what way a user has extended the hierarchy derived from 'ios': All manipulators, all insertors (i.e. functions of the form 'operator>> (istream &, T &)'), and all extractors (i.e. functions of the form 'operator<< (ostream &, T const &)' can readily be used. In addition, the different external representations can be layered if desired: For example, the compression 'streambuf' will use another 'streambuf' where it sents the compressed characters to. This way, you can directly sent the compressed stuff to a file (using a 'filebuf' which is used e.g. by 'ofstream') or to a string (using a 'stringbuf' which is used e.g. by 'ostringstream'). For more information and some commented example on how to create a new external representation, have a look at '. RIDDER: : I bought my first C++ book 4 weeks ago, so don't kill : me if I made a big mistake in design, concept, ... KUEHL: Don't mind: Apparently there are only extremely few people out there who know the 'streambuf' approach. With very few exceptions, I'm the only one promoting this approach... RIDDER: : With a better knowledge of the iostream lib, a better design : could be possible. [snip]