Boost logo

Boost :

From: Rob Stewart (stewart_at_[hidden])
Date: 2004-08-26 16:14:24


From: "Jonathan Turkanis" <technews_at_[hidden]>
>
> <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_at_[hidden]
Software Engineer                     http://www.sig.com
Susquehanna International Group, LLP  using std::disclaimer;

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk