Let's consider the following minimal code sample:
// Dummy struct
struct S
{
int a;
char * b;
// Ctors, etc...
};
void swap(S & lhs, S & rhs)
{
using std::swap;
swap(lhs.a, rhs.a);
swap(lhs.b, rhs.b);
}
Context
I know that when we intend to call a swap()
function, the proper and recommended way to proceed is to do as follows:
// Let's assume we want to swap two S instances.
using std::swap;
swap(s1, s2);
This way, ADL is able to find the proper overload if any (defined in the given type namespace), otherwise std::swap
is used.
Then I read some SO threads:
where the same idiom is used (even for built-in or pointer types), but not only when we call the std::swap()
overload but also when we define it.
Question
If the members are all built-in types (or pointer types, possibly pointers to custom types), is it still necessary/recommended to use that idiom instead of explicitly calling std::swap()
?
For example, considering the small code sample I provided, since S
members are built-in types, is it fine (well-formed) to define it as below instead:
void swap(S & lhs, S & rhs)
{
std::swap(lhs.a, rhs.a);
std::swap(lhs.b, rhs.b);
}
Or maybe is there a reason I couldn't see that would still require to use the using std::swap;
way ?
since S members are built-in types, is it fine (well-formed) to define it as below instead: [std::swap usage]
Yes. I mean, it works because std::swap
just "swaps the values a and b" if they are both MoveAssignable
and MoveConstructible
, which built-in types are.
If the members are all built-in types (or pointer types, possibly pointers to custom types), is it still necessary/recommended to use that idiom instead of explicitly calling std::swap() ?
Just for the future of your class: if one day any of its members gets replaced with a user-defined type, you might forget to modify your swap
and miss a "specialized" ADL implementation for it, still calling the generic std::swap
which could (theoretically) be inefficient yet still compile.
Actually, you don't even need to think about it if you just always use boost::swap
or implement it yourself:
template<typename T> void swap(T& a, T& b) {
using std::swap;
swap(a, b);
}