My confusion comes from "C++ Primer 5th edition" section 13.3, page 518.
Very careful readers may wonder why the
using
declaration insideswap
does not hide the declarations for theHasPtr
version ofswap
.
I tried to read its reference but still did not understand why. Could anyone explain it a little bit please? Thanks. Here is the code sample of the question.
Assume class Foo
has a member named h
, which has type HasPtr
.
void swap(HasPtr &lhs, HasPtr &rhs)
{...}
void swap(Foo &lhs, Foo &rhs)
{
using std::swap;
swap(lhs.h, rhs.h);
}
Why swap
for HasPtr
is not hidden which seems to be declared in outer scope while using std::swap
is in the inner scope? Thanks.
Because
using std::swap;
does not mean "henceforth, every 'swap' should usestd::swap
", but "bring all overloads ofswap
fromstd
into the current scope".In this case, the effect is the same as if you had written
using namespace std;
inside the function.The using-declaration
using std::swap
does not hide the functions you have declared to swapHasPtr
andFoo
. It brings the nameswap
form thestd
namespace to the declarative region. With that,std::swap
can take part in overload resolution.From the C++11 Standard:
In your case, you have:
The
using std::swap;
declaration introduces the nameswap
from thestd
namespace into the declarative region, which is the body of theswap(Foo&, Foo&)
function. The nameswap
from the global namespace is still accessible in the body of the function.If what you posted is the entirety of the function, then you don't need the
using std::swap
declaration. You could get by with just:since
swap(HasPtr &lhs, HasPtr &rhs)
is visible from the function.Now, take a look at the example below.
The line marked
A problem
is a problem since there is no function namedswap
that can work with two objects of typeint&
as argument. You can fix that using one of the following methods:Use
std::swap
explicitly.Introduce
std::swap
in the function.Effective C++ Third Edition by Scott Meyers (Item 24)
In this case and in the second block of code, compilers look for a HasPtr swap and if they don't find it they fall back on the general version in std.
The using declaration means to consider all of the std::swap overloads as if they were defined in the same namespace as the function. Since the using declaration appears in a function body, this only has an effect temporarily: within that scope.
It is identical in effect to the following:
The regular rules of overloading ensure that the first swap is the one that gets called. This is in contrast to declaring a local variable named "swap", which would hide the first overload.
Actually, The
swap
for HasPtr is hidden whileusing std::swap
in the inner scope, but in this case thestd::swap
in the inner scope is the same as theswap
for HasPtr in the outer scope.