Boost logo

Boost :

From: Marco Manfredini (marco_at_[hidden])
Date: 2000-03-06 19:32:30


Dear boosters,

I was trying to develop a couple of ideas about easy I/O, and hope some of
them are making sense somehow. I've attached code which sketches three
classes, namely bound_formatter, unbound_formatter and formatter.

1) unbound_formatter does a simple minded string replacement on the
arguments you pipe into it with the << operator, i.e.

        string s=unbound_formatter("%1=%2") << "war" << "peace"

gives 'war=peace'

        string s=unbound_formatter("a %1 is a %1") << "rose";

you know what I mean.

It uses ostrstream to render it's arguments and an overloaded operator<<
(but does not apply stream modifier)

checking for missing or superfluous arguments for the format string however
cannot be done at compile-time, but at least it is "safe".

2) bound_formatter "captures" a left handed ostream with operator<< and
routes all further input to a internal unbounded_formatter for the remaining
statement.
Upon destruction, it emits the prepared string to the captured ostream:

cout << bound_formatter("Error %1: This is %2!\n") << 12 << "silly";

(with brackets for clarity)
 (((cout << bound_formatter("Error %1: This is %2!\n")) << 12) << "silly");
<- and prints to the ostream on destruction.
                      from here it's our formatter----^
^--------^------that gets these

The nice thing about "capturing" is, that it could provide means to get
around the sticky formatting:

                 v--captures the stream for the current statement.
cout << boost::hex() << 12 ; <---------on destruction of boost::hex() the
previous number formatting mode is re-established.

boost::hex() would simply set the hex-mode on cout and pass-through all its
arguments to the captured stream.

3) formatter is a "psychic" class that can decide from it's context (through
simple overloading tricks), whether a bound_formatter or an
unbound_formatter is requiered:

        cout << formatter(msg) << 1 << 2;
works as if you had typed:
        cout << bound_formatter(msg) << 1 << 2;

        cout << (formatter(msg) << 1 << 2);
works as:
        cout << (unbound_formatter(msg) << 1 << 2);

Therefore it is relatively easy to stack formatter's without caring for
details:
        cout << formatter("The Message is %1") << (formatter(msg) << 1 << 2);

However the following doesn't work, it requires some extra substituion:
        cout << formatter("The Truth is %1") << formatter("%1 != %2") << 1 << 2;

Are there are substatial problems with the ideas? could they be useful? Or
are they simply stupid animal tricks :-)

-Marco


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