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

相關問題