Equivalence of "a @= b" and "a = a @ b"

c++

Solution

The language standard only defines the behavior of the built-in operators, not the "user defined" overloads. And from a language point of view, there is no built-in operator for `std::atomic_int` (which is formally a "user defined type"); `std::atomic_int` is a typedef for `std::atomic<int>`, which defines a number of `operator@=` overloads, but no simple `@`. So for

std::atomic_int i;
i ^= 1;

the second line becomes:

i.operator^=( 1 );

but for:

std::atomic_int i;
i = i ^ 1;

the second line becomes:

i.operator=( i.operator int() ^ 1 );

One could argue that this is part of what is implied by "the left hand argument being evaluated twice, instead of once". More generally, however, the definitions for overloaded operators are whatever the author of the operator wanted: `operator+=` could (as far as the language is concerned) actually subtract, even when `operator+` added. (I've a couple of cases where `operator+` actually does `operator+=`. This is not usually a good idea, and in my case, it only happens with classes specially designed for use with `std::accumulate`, and documented to only be used in that case.) The standard simply doesn't restrict user defined operators

Problem

It's often mooted (indeed I think even the standard alludes to it), that `a @= b` and `a = a @ b` are equivalent. Here I'm using `@` to stand in for a range of symbols such as `&` and `^`. However I doubt that they are equivalent at run-time especally if `a` is an atomic type. For example: ``` std::atomic_int a; a ^= 1; ``` (which is an atomic way of toggling `a`) is mooted as being equivalent to ``` a = a ^ 1; ``` But, this second way is not atomic due to the assignment. Therefore I doubt their literal equivalence and a compiler (irrespective of what the standard says) is not able to change the shorter form to the longer one. Am I correct?

Original source