|
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