7

Tôi đang sử dụng Visual Studio 2015.Tại sao toán tử quá tải == cho std :: weak_ptr instantiated với kiểu được xác định trong không gian tên không thể tìm thấy?

Bất cứ ý tưởng tại sao mã này biên dịch:

#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; 
} 

trong khi một này mang lại cho tôi lỗi:

#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

Hình như nó failes để tìm bộ so sánh khi Bar nằm trong một không gian tên ...

Tôi có làm gì sai không? Hoặc đây có thể là lỗi trình biên dịch không?

+2

Điều này có thể giúp: https://stackoverflow.com/a/3623643/2550156 _Bạn nên đặt quá tải toán tử trong cùng một không gian tên như lớp của bạn._ – pergy

+0

Không gian tên chứa loại, phải bao gồm các chức năng miễn phí của loại đó. Vì vậy, để trả lời * "Tôi có làm gì sai không?" *, Tôi muốn nói rằng bạn đang sử dụng không gian tên sai. – StoryTeller

+0

@StoryTeller Hàm miễn phí hoạt động trên 'std :: weak_ptr ', là ** không ** loại chứa trong 'không gian tên MyNamespace'. – Walter

Trả lời

12

Bạn nên di chuyển operator== vào không gian tên để làm cho ADL có hiệu lực; ADL cũng sẽ kiểm tra các loại được sử dụng làm đối số mẫu (ví dụ: MyNamespace::Bar) và thêm các không gian tên được liên kết (ví dụ: MyNamespace) vào tập hợp tra cứu tên. ví dụ:

namespace MyNamespace 
{ 
    class Bar; 
    bool operator==(std::weak_ptr<Bar> left, 
        std::weak_ptr<Bar> right) 
    { 
     return left.lock() == right.lock(); 
    } 

} 

Tại sao trường hợp 1 hoạt động tốt?

Vì ADL cũng hoạt động cho không gian tên chung. Đối với trường hợp thứ nhất, cả Baroperator== được định nghĩa trong cùng một không gian tên (nghĩa là không gian tên chung).

Tại sao trường hợp thứ 2 không hoạt động?

Đầu tiên lưu ý rằng std::find được định nghĩa trong namespace std, và cũng có khá nhiều operator== s được định nghĩa trong nó (với các loại thông số khác nhau). Sau đó, theo quy tắc của unqualified name lookup, khi operator== được tìm thấy tại không gian tên std, tra cứu tên sẽ dừng. Điều đó có nghĩa là không có sự trợ giúp của ADL, thì không thể tìm thấy operator== được xác định trong không gian tên chung.

+3

Trong trường hợp này, không cần tiền tố 'Bar' với' MyNamespace :: '. – VTT

+2

Có lẽ bạn có thể dám giải thích tại sao toán tử '= = 'được khai báo bên ngoài' không gian tên' không thể được sử dụng, tức là tại sao ADL lại được yêu cầu ở đây. Ngoài ra, ADL hoạt động như thế nào ở đây, vì được cho là 'std :: weak_ptr <>' nằm trong 'std', không phải' MyNamespace'. – Walter

+0

Ít nhất thì nó có tác dụng với chức năng 'find'. Nhưng tôi không thuyết phục tại sao nó không hợp lệ để khai báo toán tử bên ngoài vùng tên ... – jpo38

Các vấn đề liên quan