使用声明隐藏名称 [英] Name hiding by using declaration
问题描述
#include <iostream>
struct H
{
void swap(H &rhs);
};
void swap(H &, H &)
{
std::cout << "swap(H &t1, H &t2)" << std::endl;
}
void H::swap(H &rhs)
{
using std::swap;
swap(*this, rhs);
}
int main(void)
{
H a;
H b;
a.swap(b);
}
这是结果:
swap(H &t1, H &t2)
在上面的代码中,我尝试定义 H
的交换函数。在函数 void H :: swap(H& rhs)
中,我使用using声明使名称std :: swap可见。如果没有使用声明,则代码将无法编译,因为在类 H
中不存在带有两个参数的可用交换函数。
In the code above, I try to define a swap function of H
. In the function void H::swap(H &rhs)
, I use an using declaration to make the name std::swap visible. If there isn't an using declaration, the code cannot be compiled because there is no usable swap function with two parameters in class H
.
我在这里有一个问题。我认为,在使用using声明- using std :: swap
之后,它只是使std :: swap-STL中的模板函数可见。因此,我认为应该在 H :: swap()
中调用STL中的交换。但是结果表明,调用了 void swap(H& t1,H& t2)
。
I have a question here. In my opinion, after I used the using declaration -- using std::swap
, it just make the std::swap -- the template function in STL visible. So I thought that the swap in STL should be invoked in H::swap()
. But the result showed that the void swap(H &t1, H &t2)
was invoked instead.
所以这是我的问题:
- 为什么我不能调用swap没有使用声明?(我想这是因为在类中没有带有两个参数的交换函数。但是我不确定。)
- 为什么要调用我定义的交换而不是
H :: swap
中的STL交换?
- Why can't I invoke swap without a using declaration?(I guess it is because there is no swap function with two parameters in the class. But I am not sure. )
- Why will the swap of my definition be invoked instead of the STL swap in the
H::swap
?
推荐答案
- 为什么不使用using声明就不能调用swap?
我们从最近的封闭范围开始,向外扩展直到找到东西。
We start in the nearest enclosing scope and work our way outwards until we find something. With this:
void H::swap(H &rhs)
{
swap(*this, rhs);
}
不合格的交换
发现 H :: swap()
。然后,我们进行基于参数的查找。但是这里的规则来自 [basic.lookup.argdep ] :
Unqualified swap
finds H::swap()
. Then we do argument-dependent lookup. But the rule there is, from [basic.lookup.argdep]:
让 X 为不合格查找所产生的查找集(3.4.1)并让 Y 为
依赖于参数的查找(定义如下)所产生的查找集。如果 X 包含
—类成员的声明,或者
—不是 using-declaration的块范围函数声明或
—既不是函数也不是函数模板的声明
,则 Y 为空。否则, Y 是在与参数类型关联的名称空间中找到的声明集,如下所述。 [...]
Let X be the lookup set produced by unqualified lookup (3.4.1) and let Y be the lookup set produced by argument dependent lookup (defined as follows). If X contains
— a declaration of a class member, or
— a block-scope function declaration that is not a using-declaration, or
— a declaration that is neither a function or a function template
then Y is empty. Otherwise Y is the set of declarations found in the namespaces associated with the argument types as described below. [...]
由于不合格的查找集找到了类成员,因此依赖于参数的查找集为空(即,它找不到 swap(H& ;, H&)
)。
Since the unqualified lookup set finds a class member, the argument-dependent lookup set is empty (that is, it doesnt find swap(H&, H&)
).
- 为什么在
H :: swap
中调用我定义的交换而不是STL交换?
- Why will the swap of my definition be invoked instead of the STL swap in the
H::swap
?
添加时:
void H::swap(H &rhs)
{
using std::swap;
swap(*this, rhs);
}
现在不合格交换
发现 std :: swap()
和不是 H :: swap()
前者在更内部的范围内声明。 使用std :: swap;
与上述规则中的任何条件都不匹配,这会导致 Y 为空(这不是类成员,它是 using-declaration ,并且是一个功能模板)。结果,依赖于参数的查找集的确包含在关联命名空间中找到的声明-包括 swap(H& ;, H&)
(由于 H
在全局名称空间中)。我们最终有两个候选超载-您的首选,因为它是非模板。
now unqualified swap
finds std::swap()
and not H::swap()
, since the former is declared in a more inner scope. using std::swap;
does not match any of the criteria in the above-stated rule that would lead to Y being empty (it's not a class member, it is a using-declaration, and it is a function template). As a result, the argument-dependent lookup set does include declarations found in associated namespaces - which includes swap(H&, H&)
(since H
is in the global namespace). We end up with two overload candidates - and yours is preferred since it's the non-template.
请参见 Xeo的答案(将交换添加到您的班级的首选方法)。基本上,您要编写:
See Xeo's answer on the preferred way to add swap to your class. Basically, you want to write:
struct H {
friend void swap(H&, H&) { ... }
};
这将由ADL(并且仅由ADL)找到。然后只要有人打电话交换正确的话:
This will be found by ADL (and only by ADL). And then whenever anybody calls swap correct:
using std::swap;
swap(a, b);
查找将在适当的位置找到您的个人。
Lookup will find yours where appropriate.
这篇关于使用声明隐藏名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!