swap
Functions Should Call swap
, Not std::swap
There is one important subtlety in this code: Although it doesn’t matter in this particular case, it is essential that swap
functions call swap
and not std::swap
. In the HasPtr
function, the data members have built-in types. There is no type-specific version of swap
for the built-in types. In this case, these calls will invoke the library std::swap
.
However, if a class has a member that has its own type-specific swap
function, calling std::swap
would be a mistake. For example, assume we had another class named Foo
that has a member named h
, which has type HasPtr
. If we did not write a Foo
version of swap
, then the library version of swap
would be used. As we’ve already seen, the library swap
makes unnecessary copies of the string
s managed by HasPtr
.
We can avoid these copies by writing a swap
function for Foo
. However, if we wrote the Foo
version of swap
as:
void swap(Foo &lhs, Foo &rhs)
{
// WRONG: this function uses the library version of swap, not the HasPtr version
std::swap(lhs.h, rhs.h);
// swap other members of type Foo
}
this code would compile and execute. However, there would be no performance difference between this code and simply using the default version of swap
. The problem is that we’ve explicitly requested the library version of swap
. However, we don’t want the version in std
; we want the one defined for HasPtr
objects.
The right way to write this swap
function is:
void swap(Foo &lhs, Foo &rhs)
{
using std::swap;
swap(lhs.h, rhs.h); // uses the HasPtr version of swap
// swap other members of type Foo
}
Each call to swap
must be unqualified. That is, each call should be to swap
, not std::swap
. For reasons we’ll explain in § 16.3 (p. 697), if there is a type-specific version of swap
, that version will be a better match than the one defined in std
. As a result, if there is a type-specific version of swap
, calls to swap
will match that type-specific version. If there is no type-specific version, then—assuming there is a using
declaration for swap
in scope—calls to swap
will use the version in std
.
Very careful readers may wonder why the using
declaration inside swap
does not hide the declarations for the HasPtr
version of swap
(§ 6.4.1, p. 234). We’ll explain the reasons for why this code works in § 18.2.3 (p. 798).