Hacker News new | past | comments | ask | show | jobs | submit login

>They had a golden opportunity to fix it, but even with C++17 and the expression "a(b(), c());", it is still left indeterminate whether b() or c() will be invoked first.

If the order of b() and c() matter, then they shouldn't be in the same statement. That is an abomination. What you little you gain in terseness, you more than make up for in future headaches.




That is not an abomination. Turning this:

    int val = a(b(c(), d()), e(f(), g()));
Into this:

    auto _1 = c();
    auto _2 = d();
    auto _3 = b(_1, _2);
    auto _4 = f();
    auto _5 = g();
    auto _6 = e(_4, _5);
    int val = a(_6);
Is the abomination.

Expecting every programmer to know that a(b(), c()); may call b() first or may call c() first is an abomination. Having a programmer's app work fine on most PCs, and then suddenly having a security vulnerability that takes down my server because a compiler dev decided to exploit this on my system in order to save two clock ticks on a 4GHz CPU is an abomination.

Here's a more tangible use case:

    template<typename... P> void print(P&&...);
    print("The value of: ", binaryObject.getNextToken(), " is ", binaryObject.getNextToken(), "\n");
Looks sensible, until you find out that the compiler decides to switch the parameter ordering and you get the value before the name.

And it's not just me: the point of that PR was because people were doing exactly that with cout << next() << next(); and they clarified the rules so that was permissible. They just ignored function calls, so we are stuck using uglier than sin operator overloading of left-shift for our print statements, if we want predictable argument evaluation. Apparently the 'performance penalty' there is reasonable, so why not for function calls? So now we have to remember that in C++17, cout's ordering is left-to-right, yet print()'s ordering is effectively completely random.


But this is not particularly good imperative style. You want that to be line-based when expressions have side effects. ("one thing after another"):

  auto key = binaryObject.getNextToken();
  auto value = binaryObject.getNextToken();
  print("The value of: ", key, " is ", value, "\n");
Of course if you are calling pure functions you can use nested expressions. And then the order of evaluation does not matter.


I believe the issue is that C++ does not track what are, and are not pure functions, so the ordering optimisation is, in general, unsafe.


> You want that to be line-based when expressions have side effects.

No, I really don't. I don't want three lines instead of one line of code. And I don't want two named variables leaking into my scope. (I could encapsulate the block with {} here, but if print returned a value that I wanted to capture, then I couldn't do that.)


>int val = a(b(c(), d()), e(f(), g()));

I'll stick by my original assertion. If the order of those invocations matter, then they shouldn't be on the same line, regardless of whether the actual behavior is well-defined or not. Just one example of what can go wrong: parameter reordering is often done automatically by tools, or manually by someone who is not intimately familiar with the code, such as six-months-in-the-future you.

Six operations with side effects--especially conflicting side-effects--belong on six lines. Six lines on your screen is not worth the days potentially spent searching for a future bug.




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

Search: