为什么使用std::swap不会在外部范围中隐藏其他swap函数 < C++引物第五,第13.3节:

为什么使用std::swap不会在外部范围中隐藏其他swap函数 < C++引物第五,第13.3节:,c++,namespaces,hide,overloading,swap,C++,Namespaces,Hide,Overloading,Swap,非常仔细的读者可能会想,为什么swap内部的using声明没有隐藏HasPtr版本swap(6.4.1)的声明。我们将在18.2.3中解释此代码工作的原因 以下是示例代码: void swap(HasPtr &lhs, HasPtr &rhs) {...} void swap(Foo &lhs, Foo &rhs) { using std::swap; swap(lhs.h, rhs.h); } 事实上,我想知道为什么使用std::swap不会

非常仔细的读者可能会想,为什么swap内部的using声明没有隐藏HasPtr版本swap(6.4.1)的声明。我们将在18.2.3中解释此代码工作的原因

以下是示例代码:

void swap(HasPtr &lhs, HasPtr &rhs)
{...}

void swap(Foo &lhs, Foo &rhs)
{
    using std::swap;
    swap(lhs.h, rhs.h);
}
事实上,我想知道为什么
使用std::swap
不会在
无效交换(Foo&lhs,Foo&rhs)的范围内隐藏
无效交换(HasPtr&lhs,HasPtr&rhs)
?相反,似乎
std::swap
函数和
void swap(HasPtr&lhs,HasPtr&rhs)
被重载了

这与下面的语句相反(引用C++入门第五,6.4.1节):

如果我们在内部作用域中声明名称,则该名称将隐藏在外部作用域中声明的名称的用法。名称不会跨作用域重载

我们考虑下面的例子:

#include<iostream>
namespace a{
    void f(int a){  std::cout<< "a::f(int)";}
}
void f(double a){ std::cout<< "f(double)";}

int main(){
  using a::f;
    f(1.11);
}
这意味着这里正在使用函数
void f(int a)
,尽管
void f(double a)
会更匹配(但它是隐藏的)

总而言之,似乎 (1)
使用std::swap
重载第一种情况下外部作用域中的所有
swap
函数 (2)
在第二种情况下,使用a::f
隐藏外部作用域中的所有
f
函数

我的问题是,为什么会有这样的差异

顺便说一句,这与,所有的答案都声称所有的交换函数都是超负荷的,没有解释为什么,所以我在这里开始另一个问题

当您使用

using a::f;
您将
a::f
的声明带到声明区域的范围。声明区域部分在这里是关键

在您的例子中,它是
main
的声明性区域。
main
中没有其他的
f
声明。因此,
f
解析为
a::f

要使
a::f
和全局
f
从主屏幕可见,请使用:

using a::f;
void f(double a){ std::cout<< "f(double)";}
使用a::f;

void f(double a){std::coutWhy不读这本书的第18.2.3节?我不是100%确定确切的行为,但是,如果我是对的,
使用std::swap
确实隐藏了其他函数。然而,有一种称为参数相关查找(ADL)的东西具有优先级。基本上,当您编写
swap(lhs.h,rhs.h)时
,编译器首先根据ADL规则查找函数
swap
(基本上,查找名称为
swap
且类型为参数之一的函数定义类型的命名空间),然后,如果它找不到这样一个
swap
,它将调用调用站点上的
swap
函数,该调用站点是
std::swap
,因为
使用std::swap
a::f(int)您询问在哪里查找名称尝试这个#include namespace a{void f(char a){std::cout@Justin,谢谢!作为后续问题,ADL是我们不需要声明
使用std::operator>
使用std::move
使用std::forward
(如第18.2.3节所述)的原因。在这里,作者强调我们必须声明
使用std::swap
。为什么?
using a::f;
void f(double a){ std::cout<< "f(double)";}