I keep reading that swap() operation, like this for example:
template<class T>
void swap (T &a, T &b)
{
T temp (a);
a = b;
b = temp;
}
is problematic when we are dealing with Exception-safety.
What’s so wrong with it?
Furthermore, how can we solve it?
In the general implementation, assuming that any operation of
Tcanthrow, you cannot provide the strong exception guarantee which implies leaving the state exactly as it was before the operation on the event of a exception. Even if each operation onToffers the strong exception guarantee:If [1] throws, the input is left untouched, which is good. If [2] throws, and assuming the strong exception guarantee, the values are still untouched, which is good. But if it is [3] that throws,
ahas already been modified, which means that after the exception propagates up the stack, the caller will be left with a state that is neither the original nor the final states.EDIT: Furthermore, how can we solve it?
There is no general solution. But in most cases you can provide a exception safe
swapoperation for your types. Consider avector<T>, which internally manages it’s state through the use of three pointers (begin,end,capacity). The generalswapabove can throw (fail to allocate, the constructors for the internalTmight throw…), but it is trivial to provide a no-throwswapimplementation:Because copying of pointers cannot throw, the
swapabove offers the no-throw guarantee, and if you always implementswapfollowing the pattern above (using std::swap;followed by unqualified calls toswap) it will be picked up by ADL as a better match thanstd::swap.