6

Consider the following program:

#include <iostream>

int f() {
    std::cout << 0;
    return 1;
}

int main() {
    std::cout << f();
}

It outputs the following text:

01

Is this guaranteed by the standard though? The following things happen (not neccesarly in order)

  • (A) side effects of std::cout (not observable here)
  • (B) value evaluation of std::cout
  • (C) side effects of f() (print 0)
  • (D) value evaluation of f()
  • (E) side effects of the << operator (print 1)
  • (F) value evaluation of the << operator

Reading the order of evaluation rules on cppreference I managed to find the following:

  • Rule 2) says that (B) and (D) happen before (F).
  • Rule 19) (C++17) says that (A) and (B) happen before (C) and (D)

I could imagine, that there is a rule that says the side effects of a function happen before the return of a value, that means (C) happens before (D). I am not a hundred percent sure about where this is explicitely written down though. Maybe rule 11)?

That leaves (E) which I could not find a sequence rule for. Rule 2) explicitely excludes side effects from the sequence order, so:

  • What are the rules for (E)?
  • Is this guaranteed to be sequenced after the other observable side effect (C)?

Note:
I stumbled on this problem when discussing this recent question, which is related but more about sequencing of chained << operators. I wanted to ask for this specific question in a more condensed form and with more of my own reasoning behind it.

Botje
  • 21,384
  • 3
  • 27
  • 38
Jakob Stark
  • 2,340
  • 2
  • 17
  • I asked a similar question 4 years ago: https://stackoverflow.com/q/51784836/3684343 Yes, it is guaranteed by the standard, first `cout` will be evaluated, then `f()` will be evaluated (prints 0) and then `cout << 1` will be evaluated. – mch Jun 01 '22 at 10:17
  • f() is a subexpression used as an argument in a function call to operator< – Cubbi Jun 01 '22 at 14:49
  • 1
    @Cubbi no, the rule for `< – mch Jun 02 '22 at 06:29
  • 1
    @mch my comment was not about argument vs argument (which indeed became l-to-r for overloaded shifts in C++17, but also doesn't make a difference in this example), but about arguments vs body – Cubbi Jun 02 '22 at 21:24

0 Answers0