The general guideline when writing classes (using the copy-and-swap idiom) is to provide a non throwing swap member function. (Effective C++, 3rd edition, Item 25 and other resources)
However, what if I cannot provide the nothrow guarantee because my class uses a 3rd party class member that doesn't provide a swap operation?
// Warning: Toy code !!!
class NumberBuffer {
public:
...
void swap(NumberBuffer& rhs);
public:
float* m_data;
size_t m_n;
CString m_desc;
};
void swap(NumberBuffer& lhs, NumberBuffer& rhs) {
lhs.swap(rhs);
}
void NumberBuffer::swap(NumberBuffer& rhs) {
using std::swap;
swap(m_data, rhs.m_data);
swap(m_n, rhs.m_n);
swap(m_desc, rhs.m_desc); // could throw if CString IsLocked and out-of-mem
}
CString swap cannot be made no-throw, so there's the off chance the swap could fail.
Note: For rare 3rd party classes, using a smart ptr (pimpl) would be an option, but --
Note: CString is a good example as noone in his right mind (?) would start holding all members of a conceptually simple and ubiquitous class like CString via pimpl (smart ptr) because that would really look horrible -- and on the other hand, there's no (short to mid-term) chance to get the CString modified to allow fully no-throw swap.
So, is it OK to have a potentially throwing swap member function if you can't help it? (Or do you know ways around this conundrum?)
Edit: And: Can a throwing swap member be used with the copy-and-swap idiom to provide the basic guarantee if not the strong guarantee?
There is nothing inherently wrong with having a
swap
function that can potentially throw, but beware that without the strong exception guarantee inswap
, it cannot possibly be used to provide exception safety, that is, it can only be used asswap
(that is, forget about the copy-and-swap idiom for that particular class as a way of providing the strong exception guarantee... but you can still use it to reduce the amount of code --and document that it is not exception safe)Alternatively, you can move the
CString
into a smart pointer that offers a no-throwswap
(or at the very least the strong exception guarantee), not a nice solution, but it will at least be exception safe. Lastly, you can move away fromCString
altogether by using any other string library that provides whatever you need and offers a no-throw swap operation.