Boost logo

Boost :

From: Moore, Paul (Paul.Moore_at_[hidden])
Date: 2000-03-07 07:59:08


From: Dietmar Kuehl [mailto:dietmar_kuehl_at_[hidden]]
> > Basically, the idea is to make a class derived from stringstream
> [snip]
>
> Already at this point it is almost certain that it is not such a good
> idea: You should not derive from 'std::ostream' or 'std::istream' or
> any class derived thereof for a different purpose than convenient
> construction and convenient access to a specialized stream buffer.
> Instead of deriving from these classes, you normally want to create a
> new stream buffer although most people don't seem to be aware of this
> fact...

I was aware that creating a new stream buffer was the "official" way -
however, as all I was likely to do was to collect text into a string, which
is precisely what a stringstream does, it seemed unreasonable to reimplement
stringstream just for this...

Probably I should have written a wrapper, using containment - something
like:

class MyClass {
    stringstream s;
public:
    template <typename T> operator<<(T t) { s << t; return *this; }
}

This seems OK now that template members stand a chance of working... OTOH,
if I really need a friend operator<< in there (I have a sneaking suspicion I
might) then template friends are *definitely* a bit bleeding-edge for this
to be reliable yet.

> In a derived stream buffer you can direct the character wherever you
> want to have them. For example, at
> <http://www.fmi.uni-konstanz.de/~kuehl/iostream/> you can
> find a stream buffer writing to a GUI window (in this case to a Motif
> TextWidget but this can be adapted to other GUI systems quite easily).
> Although your approach using a destructor to gather all the output works
> for some situations, it does not work that smoothly in others and
personally I
> prefer to do only clean-up in destructors.

Yes, I've seen your web pages - they were my first introduction to some of
the wonderful things you can do with iostreams. The problem is that the
Windows MessageBox() function which I'm interested in here is a one-off call
- effectively, MessageBox(str) displays str in a window, and waits for the
user to acknowledge before returning. The string MUST be complete when the
call is made, otherwise you get multiple message boxes. I thought about
displaying the box on a flush(), but I couldn't be sure that the iostream
system wouldn't call flush() internally during the formatting (as flush is a
buffering thing, and buffering is supposed to be transparent to the user).

I could have a MsgStream type, with a special member function display(), but
then I need to call as

    {
        MsgStream s;
        s << "Hello!";
        s.display();
    }

This is unwieldy, as my intended use was as a debugging aid - sprinkle
little

    Msg() << "Got to line " << __LINE__;

statements through the code. For this usage, it really *needs* to be a
one-liner. And using a manipulator is no good, as manipulators need to work
on ostreams, not on derived classes... [Yes, I did think pretty hard about
all this...]

> > MyClass() << "This is some output, you can do numbers, too: "
> > << hex() << 1234;
>
> Although the compiler I'm using swallows a similar statement without
> complaint (using 'std::ostringstream()' rather than 'MyClass'; and the
> 'hex()' replaced by 'std::hex'), I think this should not compile: The
> temporary is bound to a non-const reference when passing it
> as argument to 'std::opererator<< (std::ostream&, char const*)'.

Ugh. That's a real issue. I hadn't thought of that problem, but I guess you
are right. Sounds like it should be rejected.

OK, does anybody have any other suggestions? I'm looking for a
debugging-printf type of statement, so it needs to be pretty minimal, but I
want to avoid
    1. Creating permanent stream objects
       (needs me to think of names, or use {}).
    2. Multiline incantations for one-line messages.
    3. Risk of partial messages being output (flush issue).

The printf-equivalent would be

    void Debug(const char *fmt, ...)
    {
        // va_args stuff
        char buf[/* Memory overwrite error waiting to happen */];
        vsprintf(fmt, va_args);
        MessageBox(buf);
    }

    // Usage
    Debug("Line %d", __LINE__);
    Debug("Starting to write output");

Thanks,
Paul.


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