c – 使用声明隐藏名称
#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可见.如果没有using声明,则无法编译代码,因为在H类中没有可用的带有两个参数的交换函数. 我在这里有一个问题.在我看来,在我使用了使用声明之后 – 使用std :: swap,它只是使std :: swap – STL中的模板函数可见.所以我认为应该在H :: swap()中调用STL中的swap.但结果表明,调用了空隙交换(H& t1,H& t2). 所以这是我的问题: >为什么我不能在没有使用声明的情况下调用swap?(我想这是因为在类中没有带有两个参数的交换函数.但我不确定.) 解决方法
我们从最近的封闭范围开始,然后向外工作,直到找到一些东西.有了这个: void H::swap(H &rhs) { swap(*this,rhs); } 不合格的交换找到H :: swap().然后我们做依赖于参数的查找.但是规则从[basic.lookup.argdep]开始:
由于非限定查找集找到类成员,因此依赖于参数的查找集为空(即,它找不到交换(H&,H&)).
当你添加: void H::swap(H &rhs) { using std::swap; swap(*this,rhs); } 现在不合格的swap找到std :: swap()而不是H :: swap(),因为前者是在更内部的范围内声明的.使用std :: swap;不符合上述规则中任何会导致Y为空的标准(它不是类成员,它是一个using声明,它是一个函数模板).因此,依赖于参数的查找集确实包括在相关命名空间中找到的声明 – 其中包括交换(H&,H&)(因为H在全局命名空间中).我们最终得到了两个重载候选者 – 而你的首选是非首选,因为它是非模板. 有关将swap添加到您的类的首选方法,请参阅Xeo’s answer.基本上,你想写: struct H { friend void swap(H&,H&) { ... } }; 这将由ADL(仅由ADL)发现.然后每当有人调用swap正确时: using std::swap; swap(a,b); Lookup会在适当的时候找到你的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |