Boost logo

Boost :

From: Ed Brey (brey_at_[hidden])
Date: 2000-05-30 10:42:08


From: "Beman Dawes" <beman_at_[hidden]>
> 1) Someone (Kevlin, Steve, Jens?) needs to provide the final code
and
> docs for stream_casts. Could I suggest stream_cast for the checked
> version, and unchecked_stream_cast for the unchecked version? The
> undecorated name should be the safest version.

For the unchecked version, Dave Abrahams had suggested stream_cast
with a std::nothrow_t parameter. The decision on what to call the
unchecked version probably should be based on its semantics.

Currently, the semantics of what happens if the conversion fails is
undocumented, although clearly from the code, the target type is
default initialized. The first question is, Is this a desired
semantic? I would tend to think that it is not, and instead if the
user doesn't want an exception, he should be able to specify his own
result of the cast, which leans towards having

void stream_cast(const Source source, Target& target);

where target remains unchanged if the conversion fails. This can be
handy in situations where there is a user configuration parameter
which is silently backed up by a hard coded default if missing or
invalid.

Another issue is the entire concept of having an unchecked stream
cast. In a way it is really not possible, since stringstream performs
a check of whether the conversion can succeed. Really the semantic
difference is what to do if the check fails: Should stringstream throw
or just flag the error? A sample implementation of stream_cast makes
this more clear:

std::stringstream interpreter;
interpreter.exceptions(failbit);
interpreter << std::boolalpha << arg;

Stringstream may always check if there is a failure; the presence or
absence of failbit specifies what to do if it finds a failure. One
thing this implies is that there is negligible performance impact on
having the throwing version (except when it throws, of course), or
perhaps the throwing version is faster, since it doesn't need to
default initialize the target.

Perhaps it makes sense to only have the throwing version, just to
minimize confusion. While having a pair of functions

Target stream_cast(const Source source); // can throw
void stream_cast(const Source source, Target& target); // doesn't
throw

makes sense, it is somewhat an arbitrary choice, since one could
rightfully make a version of the latter that does throw, basically as
a convenience version of the former (not that this would be a good
idea). Arbitrary choices are a source of confusion, since you can't
rely on intuition to jog your memory.

In summary, it might be that the non-throwing version is used so
rarely that it's not worth having. If it is useful, the next question
is how common is it that the default initialized target is desired if
there is an error? If the answer isn't "almost always", the target
should be passed in by reference. Then finally, what should it be
called? Unchecked is somewhat misleading, since there is a check
preventing target from containing just garbage if there is a failure.
Instead something term that differentiates what happens if the check
fails seems more appropriate, although I don't have a suggestion for
this.


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