Здається, що (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.