Ответ 1
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) Вы имеете в виду явную специализацию. Частично все еще что-то еще, а также невозможно для функций, только structs/classes. Таким образом, поскольку вы не можете специализировать 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) выбрано, потому что оно лучше подходит.