7

我使用Visual Studio 2015年为什么重载运算符==为std :: weak_ptr实例化与命名空间中定义的类型无法找到?

知道为什么这代码编译:

#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

看起来它failes到当Bar位于命名空间中时找到比较器...

我做错了什么?或者这可能是一个编译器错误?

+2

这可能会帮助:https://stackoverflow.com/a/3623643/2550156 _You应该把运算符重载在同一个命名空间为您的class._含有一种 – pergy

+0

命名空间,应包括自由函数该类型也是如此。所以要回答*“我做错了什么?”*,我会说你使用错误的命名空间。 – StoryTeller

+0

@StoryTeller免费函数对'std :: weak_ptr '有效,它不是**名称空间MyNamespace中包含的类型。 – Walter

回答

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也适用于全局命名空间。对于第一种情况,Baroperator==在相同的名称空间(即全局名称空间)中定义。

为什么第二种情况不起作用?

首先注意std::find在命名空间std定义,是有它定义了很多operator==秒(使用不同的参数类型)。然后根据unqualified name lookup的规则,当在命名空间std处发现operator==时,名称查找停止。这意味着如果没有ADL的帮助,全局名称空间中定义的operator==根本找不到。

+3

在这种情况下,不需要在'MyNamespace ::'前加'Bar'。 – VTT

+2

也许你可以解释为什么在'namespace'之外声明的'operator =='不能被使用,即为什么在这里需要ADL。另外,ADL如何在这里工作,因为'std :: weak_ptr <>'在'std'中,而不是'MyNamespace'。 – Walter

+0

至少它让我有'find'功能的工作。但我不相信为什么在命名空间之外声明运算符是无效的...... – jpo38

相关问题