Boost logo

Boost :

From: Mark Borgerding (mborgerding_at_[hidden])
Date: 2000-03-06 10:13:28


dave abrahams <abraham-_at_[hidden]> wrote:
original article:http://www.egroups.com/group/boost/?start=2379
> I'm starting this thread to provoken discussion of potential improved
> interfaces for formatted output (and possibly input). I hope this will
> eventually result in a boost library.
>
> I'm actually having a hard time convincing a colleague to avoid
printf (and
> related functions), and he has a point:
>
[snip]
> Of course, most of the downsides of printf are well-known:
> A. Not type-safe
> B. Easy to crash it
> C. Hard to extend (you need va_list, not-even-standard-yet
vsnprintf(), &c)
>

The main reason I avoid printf statements is because of the lack of
compile time checking. There can be some really unpleasant side effects.
   Anecdote:
      On a project a few years back, a really sharp C programmer made a
varargs logging function that was kinda slick. It acted about the same
as printf -- it actually fed the args into sprintf. Unfortunately, it
was a big problem when a trace message was logged that had "%n" in it.
The program puked on sprintf because it was trying to store an int into
a non-existent memory location. Boom! Access violation.
This was an *extremely* difficult bug to track down.

>
> boost::format( "%1 chickens can be found in coop number %2")
> % chicken_cnt % coop_num;

This is safer than a printf, but could still be prone to an error with
unintended formatting tags in the format string. It does not employ
compile-time checking.

>
> std::cout << x, y, z;

Well you can do
std::cout << (x, y, z);
But I don't think the results are what you would want. (It will
evaluate the expressions in left-to-right order and return z.

I played around with overloading the comma operator. The results were
pretty disasterous. Way, way too error prone. Throw a couple of
parens into the mix and the behavior is completely different from what
you intended. The worst part is the silence with which it compiles.
In this respect, it is no better than printf.

>
> P.S. Also, can't we do something about std::endl? This seems like way
too
> many characters to type just to produce a newline!
>

Put the following in your cpp file, or function.

using namespace std;
 or
using std::cout;
using std::cerr;
using std::endl;

I have a suggestion that I actually implemented.

Here is the gist of an approach I came up with at my last job. The
idea was to construct a temporary with a reference to some templated
type. Various modifiers could be done on the temporary, each of which
returned a reference to self. There is then an operator << that knows
how to insert one of these formatting objects into an ostream. All the
modifiers are applied to the ostream, the object is inserted and then
all the modifiers are set back to their original state. A helper
template function can optionally be used to create the correctly
formatting_object specialization -- this just makes the usage a little
easier.

The usage is less verbose and less error prone than applying the
modifieres directly to the ostream. It is also much safer than using
printf.

for (int i=0;i<offsets.size();++i)
    cout << "offsets[" << i << "] = "
          << format(offsets[i]).setf(cout.hex).fill('0').width(8)
          << endl;

In the above example, the following functions are used
template<class T> formatter<T> format(T);
// tmpl func to resolve type

formatter<T>::formatter(T);
//construct the formatter object

formatter<T>::setf(fmtflags); formatter<T>::fill(char);
formatter<T>::width(streamsize);
// set a modifier in the formatter object
// Note: this does not yet apply the modifier to the ostream

template <class T> ostream & operator << (ostream & os, formatter<T> &
t)
// apply modifiers to ostream
// os << t
// unapply modifiers

If there is sufficient intereset, I will see if I can recreate this
from memory. It was a very useful class to have. I miss the little
guy ;(

I remember it had modifier operations for flags, setf, width, precision.
Something it lacked was the callback insertion behavior that allows
cout << hex . I think this could be easily implemented with a list of
callbacks in the formatter object, but I haven't done this yet.

- Mark


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