4

The context of my question is the implementation of a simplistic stack-based virtual machine. My implementation of the addition and multiplication operations looks like this:

    case OP_ADD: Push(Pop() + Pop()); break;
    case OP_MUL: Push(Pop() * Pop()); break;

Since addition and multiplication are commutative operations, it doesn't matter which order the Pop calls are evaluated as long as the side effects (i.e., updating the virtual machine's stack pointer) of the first Pop call (whichever one that is) will be completed before the other Pop call.

With subtraction and division, the order does matter, so we have to ensure we control which Pop is executed first. For example, here's the implementation of the subtraction operation:

    case OP_SUB: {
        const auto subtrahend = Pop();
        const auto minuend = Pop();
        Push(minuend - subtrahend);
        break;
    }

I've heard vague claims that C++17 has tightened up the sequence-point and sequencing rules, but I've not heard details. I'm no longer enough of a language lawyer to parse the spec confidently in this regard.

Do the changes in C++17 provide enough sequencing guarantees that subtraction could be implemented as a single expression as with addition and multiplication? Are the order of the Pop() calls and their side effects defined, implementation-defined, or unspecified?

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • 2
    related: https://stackoverflow.com/questions/38501587/what-are-the-evaluation-order-guarantees-introduced-by-c17. Trying to find a more specific one – NathanOliver Dec 21 '18 at 15:30

1 Answers1

6

No.

One of the big changes was to certain operators, such as shift operators, which become left-to-right evaluated and this affects stream insertion. But the subtraction operator is not included.

And, honestly, even if that weren't the case, I'd still recommend the code you have now because it is clearly correct when read by a human, in a way that relying on esoteric sequencing rules never will be.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055