为什么使用std::swap不会在外部范围中隐藏其他swap函数 < C++引物第五,第13.3节:
非常仔细的读者可能会想,为什么swap内部的using声明没有隐藏HasPtr版本swap(6.4.1)的声明。我们将在18.2.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不会
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)";}