pubby8 May 3, 2014 at 10:07 PM
Good article, but I'm guessing that using more than one
ThrowOnError per statement will lead to std::terminate.
e.g. in seemingly reasonable code such as:
std::cout << libfoo_create_widgets(1, &c1, ThrowOnError()) << libfoo_create_widgets(2, &c2, ThrowOnError());
Does C++ not specify an evaluation order for chained stream insertion operands? It seems to me as a C programmer that the first ThrowOnError should be destroyed before the second one gets created.
In addition to knz42's answer, note that destructors for temporary objects are always delayed until the end of the statement, at which point they run in the reverse of the order of the corresponding constructors.
It's like the author knew it was a bad idea too (he put noexcept(false) on the destructor; without which in C++11 the program terminates immediately when an exception is thrown from destructor).
If there's some way to avoid terminating when there's a double exception in the destructor, that would be good to hear!
One simple way I can think of is to reuse the same variable instead.
This will not work, as `throw_on_error` is not going to be destroyed at the end of the printing statement. Sure, you could wrap the whole thing up into a local scope, but as this trick was invented to save a couple of lines of vertical space, the usefulness of doing it seems little.
Kind of OT, but since we're talking language interop, Fortran has neither eager nor short-circuit and/or and it is completely up to the compiler what optimizations it makes. Since Fortran ABI works directly with C (and by extension C++) natively, I've seen a whole class of bugs opened up by C/C++ devs either reading or writing Fortran not aware that this could happen. Try removing that from your mental model of how boolean logic works!
Functions have a sequence point that insists their arguments are evaluated before the function is called, but having both ThrowOnError objects constructed before calling any of the other functions would still satisfy that constraint.