c++language-lawyerswapmove-semanticscopy-and-swap

Are swaps allowed to self-check?


While checking &other != this is generally not a good idea in move/copy assignment and the copy-and-swap idiom should be preferred, is it allowed for a swap to perform such a check?

Copy-and-swap idiom:

// same for move, can handle both with `(cls other)`
cls& operator=(const cls& other) {
    cls temp{ other };
    swap(*this, other);
    return *this;
}

std::swap:

template <typename T>
void swap(T& lhs, T& rhs) {
    T tmp{ std::move(lhs); }  // move ctor
    lhs = std::move(rhs);  // move assign
    rhs = std::move(tmp);  // move assign
}  // temp dtor

While clearly not helping in assignment which constructs a new temporary, sticking an if (&lhs == &rhs) { return; } at the top of swap could save on operations in some generic code.

Does the standard allow this, or does it say the (2+1) moves are always performed? Are there some reasons why it would not work?


Solution

  • Language doesn't prevent you from introducing such a check, but self-swap is not expected to be an overly frequent operation, while checking if you swap the same object will require you to pay for itself in every swap, no matter if it's the same object or not.

    I.e. the performance gain is questionable, because:

    1. The swap implementation you have given can cover this scenario anyway
    2. If you don't self-swap objects on regular basis, you'll most likely waste more resources on the self-checking, than you'd otherwise waste on a few (redundant) move operations