为什么找不到用命名空间中定义的类型实例化的 std::weak_ptr 的重载运算符==?
Why overloaded operator== for std::weak_ptr instantiated with type defined in namespace can't be found?
我正在使用 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;
}
Error C2678 binary '==': no operator found which takes a left-hand
operand of type 'const std::weak_ptr' (or there is
no acceptable
conversion) test_cppunit_interpreter_base_multi_output c:\program
files (x86)\microsoft visual studio 14.0\vc\include\utility 216
当 Bar
位于命名空间时,似乎无法找到比较器...
我是不是做错了什么?或者这可能是编译器错误?
您应该将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 的规则,当在命名空间 std
处找到 operator==
时,名称查找停止。这意味着如果没有 ADL 的帮助,全局命名空间中定义的 operator==
将根本找不到。
我正在使用 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;
}
Error C2678 binary '==': no operator found which takes a left-hand operand of type 'const std::weak_ptr' (or there is no acceptable conversion) test_cppunit_interpreter_base_multi_output c:\program files (x86)\microsoft visual studio 14.0\vc\include\utility 216
当 Bar
位于命名空间时,似乎无法找到比较器...
我是不是做错了什么?或者这可能是编译器错误?
您应该将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 的规则,当在命名空间 std
处找到 operator==
时,名称查找停止。这意味着如果没有 ADL 的帮助,全局命名空间中定义的 operator==
将根本找不到。