- is the proper use of
swap
. Write it this way when you write “library” code and want to enable ADL (argument-dependent lookup) onswap
. Also, this has nothing to do with 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 ...
}
- Here is the proper way to provide a
swap
function for your class:
namespace Foo {
class Bar{}; // dummy
void swap(Bar& lhs, Bar& rhs) {
// ...
}
}
If swap
is now used as shown in 1), your function will be found. Also, you may make that function a friend if you absolutely need to, or provide a member swap
that is called by the free function:
// 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);
}
...
- You mean an explicit specialization. Partial is still something else and also not possible for functions, only structs / classes. As such, since you can’t specialize
std::swap
for template classes, you have to provide a free function in your namespace. Not a bad thing, if I may say so. Now, an explicit specialization is also possible, but generally you do not want to specialize a function template:
namespace std
{ // only allowed to extend namespace std with specializations
template<> // specialization
void swap<Bar>(Bar& lhs, Bar& rhs) noexcept {
// ...
}
}
- No, as 1) is distinct from 2) and 3). Also, having both 2) and 3) will lead to always having 2) picked, because it fits better.