
From: "Jonathan Turkanis" <technews@kangaroologic.com>
<boost/io/null_stream.hpp>:
I don't understand the stated rationale for this stream. Are you saying someone might want to use it to implement a command-line interface?
It may not be worded extremely well, but it certainly doesn't say that. (Something I noticed reading the rationale is the incorrect "an user." That should be "a user" since "user" doesn't start with a vowel sound. (Isn't English grand?)
An alternative rationale would be this: sometimes a C++ interface requires that the user pass an ostream to receive output, but the user doesn't care about the output. I have seen a request for a stream like this on comp.lang.c++, and I think it would be a moderately useful
It is a useful idea. I'd word the rationale more like this: "There are occasions in which one needs to provide an input or output stream(buf) to a function, but when there should be no input or all output should be ignored. In such situations, a null stream(buf), the IOStreams equivalent of *nix's /dev/null and Windows/DOS' NUL:, is needed."
component. Using my library it can be implemented as follows (as a narrow-character sink, for simplicity):
struct null_sink : sink { void write(const char*, std::streamsize) { } }; typedef stream_facade< null_sink<char> > null_ostream; etc.
This actually allows a null stream to be buffered, which improves efficiency even if you're going to throw the output away.
That's an important distinction, over and above any simplicity of definition. You should provide a null sink, source, istream, and ostream in your submission.
----------------------------------------
<boost/io/value_stream.hpp>:
As above, the rationale doesn't make sense. Unlike above, however, I can't think of a reasonable alternative rationale. BTW, it can be
"On occasion, you may need to provide an input stream(buf) to a function that only ever returns a particular character, and never runs out of that character. This is analogous to special files in *nix such as /dev/zero, which returns as many zeroes as you care to read from it. In those situations, you need value stream(buf)s."
------------------------------------------
<boost/io/iomanip.hpp>
- basic_ios_form: I don't understand what this template is supposed to do. You need a better description and some examples. Otherwise, I vote to reject.
It wasn't clear to me either, but I think I understand it to provide a means to capture a set of manipulations one wants applied to a stream so that the entire set can be applied at once. An interesting design aspect, which I only noticed upon writing this, is that the mfs fill(), precision(), width(), etc., all return a reference to the instance. That means that one can create a temporary, unnamed instance and then chain calls to those mfs to set all of the attributes desired. This is more compact and readable than using std::setfill, std::setprecision, std::setw, etc.: std::cout << std::setfill(' ') << std::setprecision(3) << std::setw(10) << ... std::cout << boost::io::basic_ios_form() .fill(' ') .precision(3) .width(10) << ... That really lends itself to writing readably. You can also assume that a using directive is in effect, yielding: cout << setfill(' ') << setprecision(3) << setw(10) << ... cout << basic_ios_form().fill(' ').precision(3).width(10) << ... That tips the scale in favor of the std manipulators. Beyond the use of namespaces, the remaining question is whether using boost::io::basic_ios_form is superior to: std::cout.fill(' '); std::cout.precision(3); std::cout.width(10); std::cout << ... After all of that, you might question the utility of boost::io::basic_ios_form, but don't forget that you can create an instance and then reuse it. Consequently, with a better name, I think it is useful.
- skipl, multi_skipl: These sound useful too, though I agree with Pavel that the names are too cryptic.
std::endl is the precendent. I don't think skipl is too cryptic. Making it less so means making it longer and that reduces its value as a manipulator. (Too cryptic outweights a short name, but I don't think this fits the "too cryptic" category.)
- multi_skipper: I'm not sure I see why this is needed; how often do you need to skip a sequence of repeated characters? Id rather
When parsing, it is often useful to ensure that there were exactly 10 spaces between one token and the next, for example.
see a utility that skips a certain specified sequence of characters, and sets failbit otherwise, as described by Dietmar Kuehl here: http://tinyurl.com/3jzwg
I agree that the generalized version that permits skipping an arbitrary string is likewise useful, but to duplicate multi_skipper's functionality, you'd have to create a string with the desired number of a character and then skip that. When you want to skip a certain number of one character, multi_skipper is better. The generalized class could, of course, provide both capabilities rather trivially.
- multi_newer: How often do you need to write multiple copies of a character to a stream? And isn't it easy to do so already? The name is bad, too. I vote to reject.
I'm sure one doesn't need to write multiple copies of a character to a stream too often, but why reject this manipulator on the grounds that it isn't needed very often? A generalized version that takes a string would be useful, too.
- multi_newl: Same as multi_newer. I don't see the need for inserting long sequences of newline characters.
There are occasions in which one wants to insert multiple newlines. As a complement to newl, I don't see a problem with keeping multi_newl.
- newl: This is a good idea. But I think this may be one of the rare components which I would like to see added to the standard library but not to boost. If it were part of the standard, every C++ programmer would be expected to know what it means. But I can't see myself including a boost header just to avoid writing "\n": most people won't know what newl it means, so rather than being self-documenting using it would be self-obfuscating. I vote to reject.
That seems a particularly bad approach. It won't get into the Standard for quite some time and, in the meantime, users can use it and prove its soundness and value. As it happens, inserting "\n" is slower than using newl because of the formatted I/O logic of streams and because of the invocation of (in effect, at least) strlen(). -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;