Кажется, что (2) ( свободное положение swapв том же пространстве имен, где объявлен определяемый пользователем класс ) является единственным допустимым способом предоставления swapопределяемого пользователем класса, поскольку добавление объявлений в пространство имен stdобычно является неопределенным поведением. Расширение пространства имен std (cppreference.com) :
Неопределенное поведение заключается в добавлении объявлений или определений в пространство имен stdили в любое пространство имен, вложенное в него std, за некоторыми исключениями, указанными ниже.
И swapне обозначается как одно из таких исключений. Поэтому добавление собственной swapперегрузки в stdпространство имен - это неопределенное поведение.
Также сказано, что стандартная библиотека использует неквалифицированный вызов swapфункции для вызова swapпользовательского класса для пользовательского класса, если такой пользовательский swapпредоставляется.
Возможность замены (cppreference.com) :
Многие стандартные библиотечные функции (например, многие алгоритмы) ожидают, что их аргументы будут соответствовать Swappable , что означает, что каждый раз, когда стандартная библиотека выполняет обмен, она использует эквивалент using std::swap; swap(t, u);.
своп (www.cplusplus.com) :
Многие компоненты стандартной библиотеки (в std) вызове swapв качестве неквалифицированным образом , чтобы пользовательские перегрузок для неосновных видов называться вместо этого дженерик: Пользовательские перегруженных swapобъявленные в том же пространстве имен типа , для которых они предоставляются выбраны через поиск, зависящий от аргументов, в этой универсальной версии.
Но обратите внимание, что прямое использование std::swapфункции для пользовательского класса вызывает общую версию std::swapвместо пользовательской swap:
my::object a, b;
std::swap(a, b); // calls std::swap, not my::swap
Поэтому рекомендуется вызывать swapфункцию в пользовательском коде так же, как это делается в стандартной библиотеке:
my::object a, b;
using std::swap;
swap(a, b); // calls my::swap if it is defined, or std::swap if it is not.