Background
Consider the following code:
#include <utility>
namespace ns
{
struct foo
{
foo() : i(0) {}
int i;
private:
foo(const foo&); // not defined,
foo& operator=(const foo&); // non-copyable
};
void swap(foo& lhs, foo& rhs)
{
std::swap(lhs.i, rhs.i);
}
}
template <typename T>
void do_swap(T& lhs, T& rhs); // implementation to be determined
int main()
{
ns::foo a, b;
do_swap(a, b);
}
In C++03, this implementation of do_swap would be considered "broken":
template <typename T>
void do_swap(T& lhs, T& rhs)
{
std::swap(lhs, rhs);
}
By explicitly specifying std::, it prohibits ns::swap from being found via argument-dependent lookup. (It then fails to compile because std::swap tries to copy a foo, which is not allowed.) Instead, we do this:
template <typename T>
void do_swap(T& lhs, T& rhs)
{
using std::swap; // allow std::swap as a backup if ADL fails to find a swap
swap(lhs, rhs); // unqualified call to swap, allow ADL to operate
}
Now ns::swap is found and std::swap, being less specialized, is not used. It's uglier, but it works and is understandable in hind-sight. boost::swap wraps this up nicely for us (and provides array overloads):
#include <boost/swap.hpp>
template <typename T>
void do_swap(T& lhs, T& rhs)
{
boost::swap(lhs, rhs); // internally does what do_swap did above
}
Question
Does std::swap take on the behavior of boost::swap in C++11? If not, why?
To me it seems obvious that it ought to. Any code broken by the change was probably quite flimsy in the first place (algorithms and containers, like std::sort and std::vector, were underspecified; implementations were allowed to call ADL swap's or not indeterminately), so the change would be for the better. Additionally, std::swap is now defined for arrays, so change at all certainly isn't out of the question.
However, while §17.6.3.2 specifies that all calls to swap within the standard library must be done without std:: qualification (fixing the problem with algorithms and containers noted above), it fails to touch on std::swap itself. It even gives examples of swapping values that include using std::swap;. Likewise §20.2.2 (where std::swap is specified) doesn't say a word on ADL.
Lastly, GCC does not enable ADL in their std::swap implementation (nor does MSVC, but that's not saying much). So I must be wrong that std::swap takes on the behavior of boost::swap, but I don't understand why the change wasn't made. :( And I'm not alone!