使用声明隐藏名称 [英] Name hiding by using declaration

查看:78
本文介绍了使用声明隐藏名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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.

所以这是我的问题:


  1. 为什么我不能调用swap没有使用声明?(我想这是因为在类中没有带有两个参数的交换函数。但是我不确定。)

  2. 为什么要调用我定义的交换而不是 H :: swap 中的STL交换?

  1. 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. )
  2. Why will the swap of my definition be invoked instead of the STL swap in the H::swap?


推荐答案



  1. 为什么不使用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&)).



  1. 为什么在 H :: swap 中调用我定义的交换而不是STL交换?

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆