为什么使用std::swap不会在外部范围中隐藏其他交换函数

Why using std::swap does not hide other swap functions in the outer scope

本文关键字:隐藏 范围 其他 函数 交换 外部 std swap 为什么      更新时间:2023-10-16

在C++Primer第5版中,第13.3节:

非常细心的读者可能会想,为什么swap中的using声明没有隐藏swap的HasPtr版本(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);
}

事实上,我想知道为什么using std::swap不会将void swap(HasPtr &lhs, HasPtr &rhs)隐藏在void swap(Foo &lhs, Foo &rhs)的范围内?相反,似乎std::swap函数和void swap(HasPtr &lhs, HasPtr &rhs)正在过载。

这与以下声明相反(引用自C++Primer 5th,第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);
}

在这种情况下,当我们使用using a::f时,它将函数void f(double a)隐藏在外部范围中。因此,我们得到以下输出

a::f(int) 

这意味着函数void f(int a)在这里被使用,尽管void f(double a)会更好地匹配(但它是隐藏的)。

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

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

顺便说一句,这与C++中的函数隐藏和使用声明有关,其中所有的答案都声称所有的交换函数都是重载的,但没有解释为什么,所以我在这里打开了另一个问题。

使用时

using a::f;

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

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

要使a::f和全局f从main可见,请使用:

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

如果执行此操作,则a::f和全局fmain都可用。

看到它在工作https://ideone.com/ySvGlP.