This is a really well-formed program that has two equally valid execution paths, so both compilers are right.
a[1] = a.size()
In this expression, evaluating two operands = has no effect.
§1.9 / 15 [intro.execution] Unless noted, evaluations of the operands of individual operators and subexpressions of individual expressions have no consequences.
However, function calls do not alternate, so the operator[] and size calls are actually indefinitely sequenced rather than sequence-dependent.
§1.9 / 15 [intro.execution] Each estimate in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the body of the called function is executed is indefinitely ordered with respect to the execution of the called function.
This means that function calls can be made in one of two orders:
operator[] then sizesize , then operator[]
If the key does not exist and you call operator[] with this key, it will be added to the map, thereby resizing the map. Thus, in the first case, the key will be added, the size will be received (now it is 1), and 1 will be assigned to this key. In the second case, the size will be obtained (which is 0), the key will be added, and 0 will be assigned to this key.
Note that this is not a situation that causes undefined behavior. undefined behavior occurs when two modifications or modifications and the reading of the same scalar object are not affected.
§1.9 / 15 [intro.execution] If the side effect of a scalar object does not affect any other side effect on the same scalar object or the calculation of a value using the value of the same scalar object, the behavior is not defined.
In this situation, they are not biased, but vaguely ordered.
So, we have two equally valid order of execution of the program. Or it can happen, and both give a reliable result. This is unspecified behavior.
§1.3.25 [defns.unspecified]
unspecified behavior
behavior, for a well-formed program design and correct data, which depends on the implementation
So, to answer your questions:
Which compiler is right?
Both of them.
Am I doing something wrong?
Maybe. It is unlikely that you will want to write code that has two execution paths like this. Undefined behavior may be okay, unlike undefined behavior, because it can be allowed for one observable output, but it’s not worth it in the first place if you can avoid it. Instead, do not write code that has such ambiguity. Depending on what exactly you want to set the correct path, you can do one of the following:
auto size = a.size(); a[1] = size;
Or:
a[1]; a[1] = a.size(); // value is 1
If you want the result to be 1 , and you know that the key does not exist yet, you can of course do the first code, but assign size + 1 .