It seems that (2) (free standing swap
in the same namespace where the user-defined class is declared) is the only allowed way to provide swap
for a user-defined class, because adding declarations to namespace std
is generally an undefined behavior. Extending the namespace std (cppreference.com):
It is undefined behavior to add declarations or definitions to namespace std
or to any namespace nested within std
, with a few exceptions noted below
And swap
is not denoted as one of those exceptions. So adding your own swap
overload to the std
namespace is an undefined behavior.
It's also said that the standard library uses an unqualified call to the swap
function in order to call user-defined swap
for a user class if such user-defined swap
is provided.
Swappable (cppreference.com):
Many standard library functions (for example, many algorithms) expect their arguments to satisfy Swappable, which means that any time the standard library performs a swap, it uses the equivalent of using std::swap; swap(t, u);
.
swap (www.cplusplus.com):
Many components of the standard library (within std
) call swap
in an unqualified manner to allow custom overloads for non-fundamental types to be called instead of this generic version: Custom overloads of swap
declared in the same namespace as the type for which they are provided get selected through argument-dependent lookup over this generic version.
But note that directly using the std::swap
function for a user-defined class calls the generic version of std::swap
instead of the user-defined swap
:
my::object a, b;
std::swap(a, b); // calls std::swap, not my::swap
So it is recommended to call the swap
function in user code in the same way as it is done in the standard library:
my::object a, b;
using std::swap;
swap(a, b); // calls my::swap if it is defined, or std::swap if it is not.