以下非常简单的代码将无法编译
#include <vector>
#include <string>
namespace Foobar {
struct Test {
std::string f;
std::uint16_t uuid;
};
}
bool operator==(const Foobar::Test& lhs, const Foobar::Test& rhs){
return lhs.f == rhs.f && lhs.uuid == rhs.uuid;
}
int main(){
std::vector<Foobar::Test> a;
std::vector<Foobar::Test> b;
if(a==b){
}
return 0;
}
https://godbolt.org/g/zn6UgJ https://godbolt.org/g/zn6UgJ
不会在我拥有的任何编译器中编译。
虽然以下
#include <vector>
#include <string>
namespace Foobar {
struct Test {
std::string f;
std::uint16_t uuid;
};
bool operator==(const Foobar::Test& lhs, const Foobar::Test& rhs){
return lhs.f == rhs.f && lhs.uuid == rhs.uuid;
}
}
int main(){
std::vector<Foobar::Test> a;
std::vector<Foobar::Test> b;
if(a==b){
}
return 0;
}
https://godbolt.org/g/o4pc1b https://godbolt.org/g/o4pc1b
编译得很好,这让我想std::vector<T>
比较运算符在以下名称空间中查找T
,为什么它不考虑全局命名空间?
普通的非限定名称查找开始在使用名称的上下文中查找,并沿着封闭范围链向上查找。它停止在包含匹配名称的最嵌套范围内。即使后来确定由此找到的名称不合适(例如,函数重载对于给定调用不可行;或者成员函数不可访问),情况也是如此。
这里,查找的上下文是std::operator==(vector, vector)
,所以它开始在命名空间中查找std
。有大量的超载operator==
在命名空间中std
,因此普通查找就在那里停止,永远不会到达全局命名空间。
在第二个示例中,通过依赖于参数的查找来找到重载。除了非限定查找之外,此查找还专门针对函数调用中的函数名称执行,并在与调用参数类型关联的作用域中查找名称。在示例中,命名空间Foobar
与....关联Foobar::Test
,因此依赖于参数的查找搜索该名称空间并找到Foobar::operator==
.
因此,自由函数在逻辑上是类公共接口的一部分 - 例如重载运算符 - 通常应在与类本身相同的命名空间中定义,以使参数相关的查找有机会工作。std::operator==(vector, vector)
就是一个很好的例子 -a==b
在您的示例中,通过依赖于参数的查找方式工作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)