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