1) является правильным использованием из swap
. Пишите это таким образом, когда вы пишете код «библиотеки» и хотите включить ADL (поиск, зависящий от аргументов) на swap
. Кроме того, это не имеет ничего общего с SFINAE.
// some algorithm in your code
template<class T>
void foo(T& lhs, T& rhs){
using std::swap; // enable 'std::swap' to be found
// if no other 'swap' is found through ADL
// some code ...
swap(lhs, rhs); // unqualified call, uses ADL and finds a fitting 'swap'
// or falls back on 'std::swap'
// more code ...
}
2) Это правильный способ предоставить функцию swap
для вашего класса.
namespace Foo{
class Bar{}; // dummy
void swap(Bar& lhs, Bar& rhs){
// ...
}
}
Если сейчас используется swap
, как показано в 1), ваша функция будет найдена. Кроме того, вы можете сделать эту функцию другом, если вам абсолютно необходимо, или предоставить члена swap
, который вызывается бесплатной функцией:
// version 1
class Bar{
public:
friend void swap(Bar& lhs, Bar& rhs){
// ....
}
};
// version 2
class Bar{
public:
void swap(Bar& other){
// ...
}
};
void swap(Bar& lhs, Bar& rhs){
lhs.swap(rhs);
}
3) Вы имеете в виду явную специализацию. Частичное - это еще что-то и не возможно для функций, только структуры / классы. Таким образом, поскольку вы не можете специализировать std::swap
для шаблонных классов, у вас есть для предоставления бесплатной функции в вашем пространстве имен. Неплохо, если можно так сказать. Теперь также возможна явная специализация, но обычно вы не хотите специализировать шаблон функции :
namespace std
{ // only allowed to extend namespace std with specializations
template<> // specialization
void swap<Bar>(Bar& lhs, Bar& rhs){
// ...
}
}
4) Нет, поскольку 1) отличается от 2) и 3). Кроме того, наличие 2) и 3) всегда приводит к выбору 2), потому что он подходит лучше.