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.
A using declaration introduces an unqualified name as a synonym for an entity declared elsewhere. It allows a single name from a specific namespace to be used without explicit qualification in the declaration region in which it appears.
The using keyword is used to: Bring a specific member from the namespace into the current scope. Bring all members from the namespace into the current scope. Bring a base class method or variable into the current class's scope.
In Method Hiding, you can hide the implementation of the methods of a base class from the derived class using the new keyword. Or in other words, in method hiding, you can redefine the method of the base class in the derived class by using the new keyword.
You can only change the access specifiers of base members the derived class would normally be able to access. Therefore, you can never change the access specifier of a base member from private to protected or public, because derived classes do not have access to private members of the base class.
Because using std::swap;
does not mean "henceforth, every 'swap' should use std::swap
", but "bring all overloads of swap
from std
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 swap HasPtr
and Foo
. It brings the name swap
form the std
namespace to the declarative region. With that, std::swap
can take part in overload resolution.
From the C++11 Standard:
7.3.3 The using declaration
1 A using-declaration introduces a name into the declarative region in which the using-declaration appears.
using-declaration:
using typename
optnested-name-specifier unqualified-id ;using ::
unqualified-id ;The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears. [ Note: Only the specified name is so declared; specifying an enumeration name in a using-declaration does not declare its enumerators in the using-declaration’s declarative region. —end note ] If a using-declaration names a constructor (3.4.3.1), it implicitly declares a set of constructors in the class in which the using-declaration appears (12.9); otherwise the name specified in a using-declaration is a synonym for the name of some entity declared elsewhere.
In your case, you have:
void swap(Foo &lhs, Foo &rhs)
{
using std::swap;
swap(lhs.h, rhs.h);
}
The using std::swap;
declaration introduces the name swap
from the std
namespace into the declarative region, which is the body of the swap(Foo&, Foo&)
function. The name swap
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:
void swap(Foo &lhs, Foo &rhs)
{
swap(lhs.h, rhs.h);
}
since swap(HasPtr &lhs, HasPtr &rhs)
is visible from the function.
Now, take a look at the example below.
struct Bar {};
void swap(Bar& lhs, Bar& rhs)
{
}
struct Foo
{
int a;
Bar b;
};
void swap(Foo& lhs, Foo& rhs)
{
swap(lhs.a, rhs.a); // A problem
swap(lhs.b, rhs.b);
}
The line marked A problem
is a problem since there is no function named swap
that can work with two objects of typeint&
as argument. You can fix that using one of the following methods:
Use std::swap
explicitly.
void swap(Foo& lhs, Foo& rhs)
{
std::swap(lhs.a, rhs.a);
swap(lhs.b, rhs.b);
}
Introduce std::swap
in the function.
void swap(Foo& lhs, Foo& rhs)
{
using std::swap;
swap(lhs.a, rhs.a);
swap(lhs.b, rhs.b);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With