Boost logo

Boost :

From: Samuel Krempp (krempp_at_[hidden])
Date: 2002-01-28 10:15:34


On Sun, 2002-01-27 at 17:59, James Kanze wrote:
> |> The printf syntax explicitly mentions the type and formatting
> |> options for each parameter. C++'s better type checking eliminates
> |> the need for the explicit typing, and the ability to add manipulator
> |> objects eliminates the need for explicit formatting.
>
> The first isn't quite true, and won't be as long as there are implicit
> conversions. Probably the most frequent error in using printf was to
> pass a constant 0 to something like a "%6.2f". A C/C++ user expects
> this to be allowed, since I can normally use an integral constant where
> ever a floating point is needed, and a good formatting function will
> know that a floating point is expected, and do the conversion.

already, format behaves better than printf, since it does print 0 in
some way, though not as a float number but as an integral one.

If I understand you correctly, you suggest converting the arguments into
the type specified by the format-string, for instance here, convert 0 to
float before formatting it.
That's one way to extend the meaning of the type-specification in the
context of Boost.Format (where arguments's types are known).

But it does not adapt well to user types :
it's okay for a float-like user-type with conversion to float,
but not if it's a pair of floats, a rational number, etc.
For those user-types, you'd have to use a special type-specificator (for
instance "%z"), to mean "don't convert the argument".
And then in this case you have no way to specify formatting options
usually carried in the type specificator (floatfields : fixed /
scientific / default, basefields, uppercase, ..)

With my approach, format still gives the same result as printf in printf
situations (float x; format("%6.2f") % x; ),
but treats the type-scpeficator merely as a set of formatting options,
so that it can apply to any type.

It does not enforce the type-specification as you wish it would,
e.g. :
int n;
cout << format("%f") % n;
will act like :
cout << fixed << n;
not like :
cout << fixed << float(n);

but it makes it applicable to any type, without discrimination.
Indeed, treating usertypes and standard types in the same way works fine
when you translate printf's type specification into stream-state
modifications, e.g :
%x => hex
%X => hex and uppercase
%e => scientific
%E => scientific and uppercase
%f => fixed
%g => unset all floatfield bits
etc.. (see the html doc for the full list)

It is carefully designed to have the same result if the types of the
arguments are the right ones, and extends nicely to any type.

In my opinion, it's better to place the conversion out of the
format-string, e.g. :
int n;
cout << format("%f") % float(n);

Though, both approaches could be implemented at the same time, by using
a special flag to choose between them (e.g. "%d" => set formatting
options suited for ouput of a decimal number, and cast to int,
V.S "%Nd" => set options, and do Not cast to int)
but it is complicating the description of the syntax too much.

BTW, with your proposal, I guess the easiest and most performant
implementation is to cast each argument into built_in types as specified
in the format-string, and then forward those arguments, and the
format-string, to a snprintf function. (we just have to care about
buffer overflow issues. which is much simpler than handling
formatting..)

> Would it be too much to ask why boost is trying to re-invent the wheel.
> The extended printf format defined by X/Open works quite well, thank
> you, and unless someone can point out some fatal flaw with it, I would
> argue for sticking with it.

as a matter of factn boost.format does stick with it
Whatever syntax is finally adopted, there will be a way to use format in
a printf-compatible mode. (which excludes "%1" stuff)
In fact, there may very well be no other mode, I'm still hesitating
whether or not provide an extra 'short-notation' mode.

For times when you need formatting options on less than 1/10 of the
arguments, I thought it would be comfortable to type simply "%1",
instead of "%1$s"; and for the argument on which you need formatting
options, use a printf-directive inside brackets, like "%{3$6.2g}". Or
some other way to get the best from both worlds.
I guees I'll eventually ask for votes on this matter.
But in all cases, format's syntax won't reinvent printf's syntax.

-- 
Samuel

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