16

Regarding this question

What are the evaluation order guarantees introduced by C++17?

With this specification

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r3.pdf

And this text from the specification

Furthermore, we suggest the following additional rule: the order of evaluation of an expression involving an overloaded operator is determined by the order associated with the corresponding built-in operator, not the rules for function calls.

Does this mean that these two expressions are no longer equivalent?

a << b;
operator<<(a, b);

As the second one looks like a function call, hence there is no guaranteed evaluation order in the parameters?

ildjarn
  • 59,718
  • 8
  • 115
  • 201
Oded S
  • 273
  • 1
  • 4
  • 7
    That's correct, the two different syntaxes have different semantics now. The operator syntax has its peculiar semantics, the function call syntax has the (new!) semantics of function calls. – Kerrek SB Sep 25 '17 at 14:46
  • @KerrekSB This is precisely why this proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0431r0.htm was written but I don't believe it gained any traction. – ForeverLearning Oct 05 '17 at 14:33
  • @ForeverLearning: It is certainly a subject that inspires hearts, minds and proposals! – Kerrek SB Oct 05 '17 at 18:25

1 Answers1

18

"As the second one looks like a function call, hence there is no guaranteed evaluation order in the parameters?"

Indeed. [expr.call]/5 contains an example specifically covering the difference between the two cases covered in your question [emphasis mine]:

The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.

...

Note: If an operator function is invoked using operator notation, argument evaluation is sequenced as specified for the built-in operator; see [over.match.oper]. [ Example:

struct S {
  S(int);
};
int operator<<(S, int);
int i, j;
int x = S(i=1) << (i=2);
int y = operator<<(S(j=1), j=2);

After performing the initializations, the value of i is 2 (see [expr.shift]), but it is unspecified whether the value of j is 1 or 2.

— end example ]

dfrib
  • 56,823
  • 7
  • 97
  • 157