|
Boost : |
From: Karl Nelson (kenelson_at_[hidden])
Date: 2000-08-19 11:43:41
>
>
> I'll confess: I issued the original challenge which resulted in Rudiger's
> contribution. One of my big complaints with printf is that I find the format
> specifications impossible to remember, so a goal was to come up with
> something much simpler. Another issue is that printf specifiers always
> indicate something about the type of the argument to be formatted, which is
> completely unneccessary with typesafe C++. I notice you cover that by
> allowing %s to format *anything*, not just a string.
Yes, that is a definite difference in strategies. My general philosophy
has always been strict adherence to a standard even if it is poor is
better than cutting something yourself. However, this is very open for
debate.
Now in regards to mine. The prinf specifiers are made very fuzzy.
%s means any literal. %d means anything with the decimal formatted.
%x means anything with numbers printed as hex. Thus the print
indicators are more about how shall I format this and not really what
type the item is.
> > He does add some fancy things
> > like centering that mine lacks because those aren't in printf specs.
> > However, his format caps the number of arguments to the
> > format command at 9 arguments. Mine code caps out at around 256
> > because more than that was kind of pointless.
>
> I'm not sure how compelling it is to be able to format more than 9
> arguments. One upside of the boost system is that it is clear exactly which
> arguments go with a particular format string.
It certainly is not very compelling as I could count on one hand all
the times I had more than 9 arguments (though I can remember it happening).
A more direct problem is that I think that the current implementation
may always require pass by value. Thus you must specialize each
subset of const T& and T& for a given number of arguments.
Thus for 4 arguments you would need
T&, T&, T&, T&
const T&, T&, T&, T&
T&, const T&, T&, T&
T&, T&, const T&, T&
T&, T&, T&, const T&
const T&, constT&, T&, T&
T&, const T&, constT&, T&
T&, T&, const T&, constT&
T&, constT&, T&, const T&
const T&, T&, T&, const T&
....
Okay you get the point. I have tried something similar for
a general create template, when I was trying to make new private
for a class by allow GC for items through create.
The problem comes down to C++ needs a
template <class T&> foo(T t);
which means T is always a reference type.
Without this anything which tries to do format(...) with templates
will fail.
> > His is coded in charT templates. Mine is currently only 8
> > bit form. Although this is interesting I am
> > not sure how applicable it is to a UTF-8 stream. UTF-8 is exactly
> > that 8 bits (with variable length encoding.) I assume mine could be
> > changed but the details of the interactions would likely need to be
> > discussed.
>
> For some of us, being able to handle wide characters (unicode) was an
> important design criterion.
Yes. I agree. I just don't know that I would be qualified to extend
my stream properly to cover that meaning. It is a large can of
worms. I would tend to believe that my format should just be
overloaded for wide uses or charT specials and leave the default
something like this. wformat???
> > Mine is passed on a stream proxy, so it looks like a manipulator.
> > His is designed to look like a function.
>
> I think if you review the boost discussions, you'll see that I suggested
> this as a way of keeping the format string associated with its arguments as
> described above.
Right. I did notice that. But it wasn't discussed why
making the format a normal manipulator was bad.
> > Other manipulators do
> > not count as arguments in my. They do in his.
>
> Yes, I don't love this arrangement. Actually, I don't mind having the
> feature, but for ease-of-use I would prefer to see a different form of
> manipulators which enclosed the argument to which they applied. For example:
>
> boost::format("%1 != %2", fixed(boost::setprecision(5, 1.9999)), 2.0000);
>
> where fixed and setprecision(5) are being applied only to 1.9999 above.
Well mine of course escapes that unless you want variable width
specifiers.
cout <<format("%.5f != %f") << 1.9999 << 2.0000;
(whether this is implemented properly currently is open to question.
I was still early in the testing.)
> > His as functions
> > has ordering preferences, mine being a stream can not.
>
> I don't understand what you mean by "has ordering preferences".
format( foo, bar ) has a clear start and stop because (). Mine
is quite fuzzy, though endf serves that purpose.
>
> I think one of the biggest problems with Rudiger's examples is that he
> overstresses complex capabilities like nested formatting, which makes them
> hard to read. AFAICT, your example would not produce equivalent output to
> his. I think to get something equivalent to your example, we could write:
Yes, I know mine wasn't exactly equivelent. But then by following
printf mine sort of has to be non-equivelent. I am not at all
opposed to adding some char like <>^ to indicate alignment and such.
> std::cout << format("The Truth is %3%4%1 != %2\n",
> format("%3%4%1 != %2", 1.9999, 2.000, setprecision(5),fixed));
>
> > There would be no way in mine to cap the size of the two arguments
> > and center them. On the other hand standardizing how to
> > center "1000.0000 != 10000.0000" if they came out to more than the
> > recommended field length seems difficult at best. Something
> > so fancy probably should be left to the user who would
> > code to drop precision over accidentally saying
> > "1000.0000 != 1000".
>
> I think the boost strategy is to blow off the formatting if the value
> representation would be overly compromised. I think this is the same thing
> that printf does with field widths. I'm not positive, though.
Printf blows off widths in this case. Hopefully mine can do the same.
I am not sure about boost format.
--Karl
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk