[format] Reuse of the format object
Hi, I've got a question about the reuse of the boost::format object. Given this minimal testcase: ----------------------------------------------------------- #include <iostream> #include <boost/format.hpp> int main() { boost::format fmt("%|=12| %|=12| %|=12|\n"); // 1 std::cout << boost::str(fmt % "a" % "b" % "c") << boost::str(fmt % 1 % 2 % 3); // 2 std::cout << fmt % "a" % "b" % "c" << fmt % 1 % 2 % 3; } ----------------------------------------------------------- Why is 1 working while 2 produces the runtime exception:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::io::too_many_args> >' what(): boost::too_many_args: format-string referred to less arguments than were passed
? I didn't find an explanation about this in the doc & the example about the reuse of format objects here: http://www.boost.org/doc/libs/1_46_1/libs/format/example/sample_advanced.cpp Using boost 1.46.0 and g++ 4.5.2. Thanks, -- Maxime
2011/4/11 Maxime van Noppen <maxime@altribe.org>
Hi,
I've got a question about the reuse of the boost::format object. Given this minimal testcase:
----------------------------------------------------------- #include <iostream> #include <boost/format.hpp>
int main() { boost::format fmt("%|=12| %|=12| %|=12|\n");
// 1 std::cout << boost::str(fmt % "a" % "b" % "c") << boost::str(fmt % 1 % 2 % 3);
// 2 std::cout << fmt % "a" % "b" % "c" << fmt % 1 % 2 % 3; } -----------------------------------------------------------
Why is 1 working while 2 produces the runtime exception:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::io::too_many_args> ' what(): boost::too_many_args: format-string referred to less arguments than were passed
?
I believe a possible reason is that order of evaluation of the operations is unspecified. A simple example of this mechanism would be: int i = 0; cout << i++ << ++i; // what will this print? It's unspecified and compiler dependant To make your example work, try: cout << fmt % "a" % "b" % "c"; cout << fmt % 1 % 2 % 3; Regards Kris
On 04/11/2011 12:47 PM, Krzysztof Czainski wrote:
I believe a possible reason is that order of evaluation of the operations is unspecified.
A simple example of this mechanism would be: int i = 0; cout << i++ << ++i; // what will this print? It's unspecified and compiler dependant
To make your example work, try: cout << fmt % "a" % "b" % "c"; cout << fmt % 1 % 2 % 3;
Oh well, I just rewrote the operator<< calls as function calls and it becomes clear: operator<<( operator<<(std::cout, fmt % "a" % "b" % "c"), // 1 fmt % 1 % 2 % 3); // 2 The compiler may very well evaluate 2, which binds arguments into fmt, then evaluate 1 to perform the nested operator<< call but then fmt is already bound to arguments. But then, in the source code of the example I quoted previously there is this statement:
// once you call operator% again, arguments are cleared inside the object
Does there have to be at least one evaluation of the formatter before this statement becomes true? It seems so given that this example throws the same exception as above: fmt % 1 % 2 % 3; fmt % 4 % 5 % 6; std::cout << fmt; So *after being evaluated*, the call to operator% clears the formatting object, am I right? -- Maxime
Maxime van Noppen <maxime <at> altribe.org> writes:
Oh well, I just rewrote the operator<< calls as function calls and it becomes clear:
operator<<( operator<<(std::cout, fmt % "a" % "b" % "c"), // 1 fmt % 1 % 2 % 3); // 2
I think you could just write: std::cout << fmt % "a" % "b" % "c"; std::cout << fmt % 1 % 2 % 3; When the str(format&) or operator<<(std::ostream&, format&) is applied it should check and clear the format bindings. HTH, -Ryan
On 04/11/2011 06:20 PM, Ryan Gallagher wrote:
I think you could just write:
std::cout << fmt % "a" % "b" % "c"; std::cout << fmt % 1 % 2 % 3;
When the str(format&) or operator<<(std::ostream&, format&) is applied it should check and clear the format bindings. HTH,
Of course, and it works, but I don't like to be bitten without knowing what happened exactly. :) It might also be worth mentioning in the doc. -- Maxime
Maxime van Noppen <maxime <at> altribe.org> writes:
On 04/11/2011 06:20 PM, Ryan Gallagher wrote:
I think you could just write:
std::cout << fmt % "a" % "b" % "c"; std::cout << fmt % 1 % 2 % 3;
When the str(format&) or operator<<(std::ostream&, format&) is applied it
should
check and clear the format bindings. HTH,
Of course, and it works, but I don't like to be bitten without knowing what happened exactly. :) It might also be worth mentioning in the doc.
Yeah, was bitten by this too a long time back and had to look it up in the docs to understand. Does this help explain? http://www.boost.org/doc/libs/1_46_0/libs/format/doc/format.html#how_it_work... But, yeah, perhaps they should have a "don't do this" example with explanation in that section.
participants (3)
-
Krzysztof Czainski
-
Maxime van Noppen
-
Ryan Gallagher