Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Response to a comment on the blog post:

    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.


This definitely dampens the usefulness.

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.

   ThrowOnError throw_on_error;
   std::cout << libfoo_create_widgets(1, &c1, throw_on_error) << libfoo_create_widgets(2, &c2, throw_on_error);


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.


No C++ does not specify evaluation order in this case.

Remember "<<" is just that, an operator.

Only && and || have a mandated evaluation order.


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!


In that case, is a compiler allowed to instantiate both ThrowOnError objects before calling either of the C functions?


No. Overloaded operators act like functions and functions are sequence points.


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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: