|
Boost Users : |
Subject: Re: [Boost-users] Why is boost::format::operator% not declared const?
From: Anthony Foiani (tkil_at_[hidden])
Date: 2013-01-17 02:49:32
Chris, greetings --
Chris Stankevitz <chrisstankevitz_at_[hidden]> writes:
> Question 1: Is there an efficient way to do the following (and by
> "more efficient" I mean fewer format constructors and string parsing):
>
> void WriteLog(float x, float y, float z, const Employee& e)
> {
> std::cout
> << "Values: "
> << boost::format("%0.3") % x
> << e
> << boost::format("%0.3") % y
> << boost::format("%0.3") % z;
> }
Please take a look at the benchmarks mentioned in the boost.format
documentation:
http://www.boost.org/doc/libs/1_52_0/libs/format/doc/format.html#performance
They're a few years out of date, but they cover the most straight-
forward way to get the power of boost.format without quite as much
parsing / constructing overhead: make one const instance, then copy
construct to create your mutable instances.
Assuming the copy constructor is thread-safe (which, if you're not
using internal state like str() does, then it should be -- but no
guarantees...) then something like this:
// single copy to do work of parsing
static const boost::format fixed3proto( "%0.3f" );
// now clone it for each format operation
boost::format fixed3( fixed3proto );
// and use the cloned copy
fixed3 % x;
return fixed3.str();
In this situation, where you have three floats that you want formatted
a particular way, then using maniuplators on cout is reasonable; just
make sure you save the state (with ios_base_all_saver or friend).
But be aware that some of those manipulators will still be in force
when you try to emit the Employee object...
> Question 2: Is there a more efficient way to do this:
>
> std::string FloatToString(float x, int DigitsAfterDecimal)
> {
> std::ostringstream FormatStream;
> FormatStream << "%0." << DigitsAfterDecimal;
> boost::format Formatter(FormatStream.str());
> Formatter % x;
> return Formatter.str();
> }
In this particular case, since you're already building an
ostringstream, you can just use the standard manipulators:
std::ostringstream oss;
oss << std::fixed << std::setprecision( DigitsAfterDecimal ) << x;
return oss.str();
Note that ostringstream construction isn't entirely lightweight; if
you have an easy way of keeping an instance around in a thread-safe
manner, then you might be better off having a single instance per
thread, then doing:
oss.str( "" );
oss << std::fixed << std::setprecision( DigitsAfterDecimal ) << x;
return oss.str();
(Further, if that's the only thing you ever use that ostringstream
for, you can possibly shave a few more cycles off by using the flags
field directly; I don't recall if fixed and setprecision last past a
single value output.)
However, if you really do require the fastest formatting, you're
probably best off calling into the old C library with snprintf -- but
you are then responsible for sizing your buffer correctly, etc.
Happy hacking,
t.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net