global stream manipulators for the format library
I've got some code that uses the format library to format output, not out of necessity, but rather out of a wanton enjoyment derived from using the syntax, having lately (relatively) discovered boost, prefering the boost::format simple syntax to the posix printf and std::ostringstream flavored solutions. The "problem" I have is that for the output of every double, I have to specify the precision: int main() { cout << setprecision(18); cout << format("Bunner p' air: %1% torr\t\tN$_2$: %2% torr\n" " C air: %3%\t\tN$_2$: %4%") % group(setprecision(18), bunner::air::pp_av) % group(setprecision(18), bunner::N2::pp_av) % group(setprecision(18), bunner::air::c_av) % group(setprecision(18), bunner::N2::c_av) << endl; //... return 0; } Is there a graceful solution, or am I using this library beyond what it was intended for? Something like the following naturally suggests itself, but I don't think it is standard compliant: the constructor doesn't seem to like using a static object, actually the linker couldn't find the 'prmanip' object. class Fmt { public: Fmt() { cout << "duh" << endl << prmanip << constants::pi << endl; } static std::_Setprecision setpr(const int&pr) { prmanip = std::setprecision(pr); return std::setprecision(pr); } static std::_Setprecision prmanip; }; int main() { cout << setprecision(18); Fmt::setpr(18); //... Justin
le Monday 30 August 2004 19:43, findlay@cosmic.utah.edu écrivit :
I've got some code that uses the format library to format output, not out of necessity, but rather out of a wanton enjoyment derived from using the syntax, having lately (relatively) discovered boost, prefering the boost::format simple syntax to the posix printf and std::ostringstream flavored solutions. The "problem" I have is that for the output of every double, I have to specify the precision:
int main() { cout << setprecision(18); cout << format("Bunner p' air: %1% torr\t\tN$_2$: %2% torr\n" " C air: %3%\t\tN$_2$: %4%") % group(setprecision(18), bunner::air::pp_av) % group(setprecision(18), bunner::N2::pp_av) % group(setprecision(18), bunner::air::c_av) % group(setprecision(18), bunner::N2::c_av) << endl; //...
return 0; }
Is there a graceful solution, or am I using this library beyond what it was intended for?
Well, making manipulators *non* sticky was in fact a desired feature of the library. Quite a bit of work is done to insure that. Letting manipulators (and whatever other stream modification) stack from one argument formatting to the next would be much easier.. In your case, using the stream directly, with a sticky setprecision, seems natural. If you really want to use format, you can either : A/ pass the precision via printf-style syntax (at each item), e.g. : cout << format("Bunner p' air: %|1$.18| %|2$.18|") % bunner::air::pp_av % bunner::N2::pp_av << endl; Does this solution fit you ? B/ define a number + format-style wrapper class, e.g. 'StyledNumber', on which you overload operator<<(stream&, ..) so that it temporarily overrides the stream's precision parameter, and them format StyledNumber objects : cout << format("Bunner p' air: %1% %2%") % StyledNumber(bunner::air::pp_av) % StyledNumber(bunner::N2::pp_av) << endl; here, it's not much shorter than the original version, but if you replace calls to the constructor by calls to short-named wrapper function, it can improve the situation a bit and you get all the flexibility you want I can think about adding this feature as a member function to boost::format that would apply one manipulator to all items in one go, like : cout << format("Bunner p' air: %1% %2%").stick(setprecision(18)) % bunner::air::pp_av % bunner::N2::pp_av; Is it what you'd need ? There's already an undocumented member function, 'modify_item', that applies a manipulator to one "format item", so 'stick' would just have to do the same, except for all the items. The only problem is : it's only able to clone the manipulator's effects on *standard* stream parameters, while a user-defined manipulator could very well act on unknown user-defined stream parmaters (think xalloc, etc..). So such a feature would have to be documented along with the details on its limits, and interfaces full of functions-with-special-cases are better avoided IMO. Anyway I need to take some time and finally document the undocumented functions (modify_item, bind_arg, etc..), and then I might add a 'stick' function along those. In the meantime, you can use the 'modify_item' function to define an external 'stick' function. -- Samuel
On Tue, Aug 31, 2004 at 01:33:12AM +0200, Samuel Krempp wrote:
... Does this solution fit you ? ... Is it what you'd need ?
It really is just a question of style, and as you pointed out, there are other solutions more cursory, and perhaps better suited to the task. My main question is whether this "feature" were considered before, whether it would add to the utility of the class.
There's already an undocumented member function, 'modify_item', that applies a manipulator to one "format item", so 'stick' would just have to do the same, except for all the items. The only problem is : it's only able to clone the manipulator's effects on *standard* stream parameters, while a user-defined manipulator could very well act on unknown user-defined stream parmaters (think xalloc, etc..). So such a feature would have to be documented along with the details on its limits, and interfaces full of functions-with-special-cases are better avoided IMO.
Indeed.
Anyway I need to take some time and finally document the undocumented functions (modify_item, bind_arg, etc..), and then I might add a 'stick' function along those.
In the meantime, you can use the 'modify_item' function to define an external 'stick' function.
Certainly, thanks for the direction. Forasmuch I might as well store these numbers as objects that know their own accuracy and error too. Justin
On 8/30/04 7:33 PM, "Samuel Krempp"
I can think about adding this feature as a member function to boost::format that would apply one manipulator to all items in one go, like : cout << format("Bunner p' air: %1% %2%").stick(setprecision(18)) % bunner::air::pp_av % bunner::N2::pp_av; [TRUNCATE]
Wouldn't the encapsulation of several formatting changes be like the "basic_ios_form" class template I just had under review? If my template goes into Boost, maybe you can support global formatting changes that way. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com
participants (3)
-
Daryle Walker
-
Justin Findlay
-
Samuel Krempp