Short answer:
You didn't specify compiler/flags, so I'd encourage you to make sure you're building for C++17 (clang/g++ flag -std=c++17
). This should fix your result, though still might cause a compilation warning. The how and why is below. Update: Unlike clang and gcc, msvc seem to be fully conformant on this one -- gives the expected result, warning-free.
Explanation:
Unintuitively indeed, this unexpected result has nothing to do specifically with stream operations. It has to do with unsequenced evaluations of operands. See here in [intro.execution]:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced.
[...] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a memory location is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, [...] the behavior is undefined.
...
i = i++ + i; // the behavior is undefined
But behold, <<
operator (shift operators) is being noted specifically to be sequenced in the current spec (since C++17) -- see here in [expr.call]:
If an operator function is invoked using operator notation, argument
evaluation is sequenced as specified for the built-in operator;
combined with this in [expr.shift]:
The value of E1 >> E2 ... The expression E1 is sequenced before the
expression E2.
For your snippet, clang 6.0.1 gives this informative warning that according to these excerpts from the spec is not in conformance with the standard (!):
warning: multiple unsequenced modifications to 'x' [-Wunsequenced]
std::cout << (x = true) << std::endl
You can see it here live.
Note: This answer has been edited to reflect current state of things, thanks to user M.M who brought forth this enlightening SO link which refers to the appropriate bug reports on both clang and GCC.