using-declaration using std::swap 不会隐藏您声明交换HasPtr 和Foo 的函数。它将名称 swap 从 std 命名空间带到声明性区域。这样,std::swap 就可以参与重载决议。
来自 C++11 标准:
7.3.3 using 声明
1 using-declaration 将名称引入到 using-declaration 出现的声明性区域中。
使用声明:
using typenameoptnested-name-specifier unqualified-id ;
using :: unqualified-id ;
在 using-declaration 中指定的成员名称在 using-declaration 出现的声明区域中声明。 [ 注意: 只有指定的名字是这样声明的;在 using-declaration 中指定枚举名称不会在 using-declaration 的声明区域中声明其枚举数。 —结束说明 ] 如果一个 using-declaration 命名了一个构造函数(3.4.3.1),它隐式声明了一个类中的一组构造函数,其中 using-声明出现(12.9);否则,在 using-declaration 中指定的名称是其他地方声明的某个实体名称的同义词。
在你的情况下,你有:
void swap(Foo &lhs, Foo &rhs)
{
using std::swap;
swap(lhs.h, rhs.h);
}
using std::swap; 声明将来自 std 命名空间的名称 swap 引入声明区域,即 swap(Foo&, Foo&) 函数的主体。全局命名空间中的名称 swap 仍然可以在函数体中访问。
如果您发布的是整个函数,那么您不需要using std::swap 声明。您只需:
void swap(Foo &lhs, Foo &rhs)
{
swap(lhs.h, rhs.h);
}
因为swap(HasPtr &lhs, HasPtr &rhs) 在函数中是可见的。
现在,看看下面的例子。
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);
}
标记为A problem 的行是一个问题,因为没有名为swap 的函数可以使用两个int& 类型的对象作为参数。您可以使用以下方法之一解决此问题:
-
明确使用std::swap。
void swap(Foo& lhs, Foo& rhs)
{
std::swap(lhs.a, rhs.a);
swap(lhs.b, rhs.b);
}
-
在函数中引入std::swap。
void swap(Foo& lhs, Foo& rhs)
{
using std::swap;
swap(lhs.a, rhs.a);
swap(lhs.b, rhs.b);
}