我正在使用Visual Studio 2015。
知道为什么这段代码会编译:
#include <memory>
class Foo;
class Bar;
typedef std::pair<Foo*,std::weak_ptr<Bar>> Object;
typedef std::vector<Object> ObjectVect;
bool operator==( std::weak_ptr<Bar> left,
std::weak_ptr<Bar> right )
{
return left.lock() == right.lock();
}
int main( int argc, char* argv[] )
{
ObjectVect vect;
Object obj;
auto foundIter = std::find( vect.begin(), vect.end(), obj );
return 0;
}
虽然这个给了我错误:
#include <memory>
class Foo;
namespace MyNamespace
{
class Bar;
}
typedef std::pair<Foo*,std::weak_ptr<MyNamespace::Bar>> Object;
typedef std::vector<Object> ObjectVect;
bool operator==( std::weak_ptr<MyNamespace::Bar> left,
std::weak_ptr<MyNamespace::Bar> right )
{
return left.lock() == right.lock();
}
int main( int argc, char* argv[] )
{
ObjectVect vect;
Object obj;
auto foundIter = std::find( vect.begin(), vect.end(), obj );
return 0;
}
错误C2678二进制&#39; ==&#39;:找不到左侧的操作符 类型&#39; const std :: weak_ptr&#39;的操作数(或者有 不可接受 转换)test_cppunit_interpreter_base_multi_output c:\ program files(x86)\ microsoft visual studio 14.0 \ vc \ include \ utility 216
当Bar
位于命名空间中时,看起来很难找到比较器......
我做错了吗?或者这可能是编译器错误?
答案 0 :(得分:12)
您应该将operator==
移到命名空间中以使ADL生效; ADL还将检查用作模板参数的类型(即MyNamespace::Bar
),并将关联的命名空间(即MyNamespace
)添加到名称查找集中。
即。
namespace MyNamespace
{
class Bar;
bool operator==( std::weak_ptr<Bar> left,
std::weak_ptr<Bar> right )
{
return left.lock() == right.lock();
}
}
为什么第一种情况正常?
因为ADL也适用于全局命名空间。对于第一种情况,Bar
和operator==
都在同一名称空间(即全局名称空间)中定义。
为什么第二种情况不起作用?
首先请注意std::find
在命名空间std
中定义,并且其中定义了许多operator==
(具有不同的参数类型)。然后根据unqualified name lookup的规则,当在命名空间operator==
中找到std
时,名称查找将停止。这意味着如果没有ADL的帮助,将无法找到全局命名空间中定义的operator==
。