The standard library policy about move assignment is that the implementation is allowed to assume that self-assignment will never happen; this seems to me a really bad idea, given that:
remove_if
family need to take care of this corner case;So, why such a decision?
¹ Especially in library code, where implementers can liberally exploit compiler-specific hints about "branch expected outcome" (think __builtin_expect
in gcc/__assume
in VC++).
Moved from objects in std
are supposed to be discarded or assigned to prior to being reused. Anything that is not completely free beyond that is not promised.
Sometimes things are free. Like a move-constructed-from container is empty. Note that some move-assiged-from cases have no such guarantee, as some implementations may choose to move elements instead of buffers. Why the difference? One was a free extra guarantee, the other not.
A branch or other check is not completely free. It takes up a branch prediction slot, and even if predicted is merely almost free.
On top of that, a = std::move(a);
is evidence of a logic error. Assign-from a
(within std
) means you will only assign-to or discard a
. Yet here you are wanting it to have specific state on the next line. Either you know you are self-assigning, or you do not. If you do not, you are now moving from object you are also populating and you do not know it.
The principle of "do little things to keep things safe" clashes with "you do not pay for that which you do not use". In this case, the second won.