2012-10-13 126 views
6

我有一個關於使用std :: weak_ptr作爲std :: map的關鍵的問題。std :: map with std :: weak_ptr key

#include <map> 
#include <memory> 

int main() 
{ 
std::map< std::weak_ptr<int>, bool > myMap; 

std::shared_ptr<int> sharedptr(new int(5)); 
std::weak_ptr<int> weakptr = sharedptr; 

myMap[weakptr] = true; 

return 0; 
} 

上述程序並不構建和試圖編譯給出許多錯誤消息,例如:由於以下行

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xfunctional(125): error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::tr1::weak_ptr<_Ty>' 
1>   with 
1>   [ 
1>    _Ty=int 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xtree(1885) : see declaration of 'std::operator <' 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xfunctional(124) : while compiling class template member function 'bool std::less<_Ty>::operator()(const _Ty &,const _Ty &) const' 
1>   with 
1>   [ 
1>    _Ty=std::tr1::weak_ptr<int> 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\map(71) : see reference to class template instantiation 'std::less<_Ty>' being compiled 
1>   with 
1>   [ 
1>    _Ty=std::tr1::weak_ptr<int> 
1>   ] 
1>   C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xtree(451) : see reference to class template instantiation 'std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,_Mfl>' being compiled 
1>   with 
1>   [ 
1>    _Kty=std::tr1::weak_ptr<int>, 
1>    _Ty=bool, 
1>    _Pr=std::less<std::tr1::weak_ptr<int>>, 
1>    _Alloc=std::allocator<std::pair<const std::tr1::weak_ptr<int>,bool>>, 
1>    _Mfl=false 
1>   ] 

出現該問題:

myMap[weakptr] = true; 

誤差消息似乎與運營商<有關。我是否需要爲weak_ptrs定義運算符<?究竟需要定義哪些操作符才能將數據類型用作std :: map的關鍵字?

(我要指出,我已經在STD命名空間中定義的==操作符。另外,我打算使用了weak_ptr到自定義類的類型,而不是一個int。)

回答

13

C++ 11提供了合適的機制來比較std::weak_ptr,即:std::owner_less

這應該是地圖和集合的默認值。如果您正在使用的C++編譯器很難,請嘗試使用std::owner_less(如果可用)。如果它不可用,則需要提供與std::owner_less類似的機制,以便您可以適當比較std::weak_ptr對象。

+4

最終形式爲'std :: map ,U,std :: owner_less >>' – DiB

0

第三個模板參數爲std :: map <>默認爲std :: less,它通常只爲Key調用操作符<()。因此,您可以爲std :: weak_ptr <>(這可能是個壞主意)定義運算符<(),或者創建一個函數並將其作爲std :: map的第三個模板參數提供。

即使如此,我不確定這是否可以實際工作,因爲std :: map <>要求鍵是不可變的,而std :: weak_ptr <>可以在任何時候改變(指針值可以變爲空)。

struct WeakPtrLess 
{ 
    template <typename T> 
    bool operator() (const std::weak_ptr<T>& l, const std::weak_ptr<T>& r) const 
    { 
    std::shared_ptr<T> sl = l.lock(); 
    std::shared_ptr<T> sr = r.lock(); 

    return sl.get() < sr.get(); 
    } 
}; 

使用這個自己的危險。 (或者無論表達式是什麼)

+0

您可能在您的比較器類中指的是'operator()'而不是'operator <''。 – PiotrNycz

+0

@PiotrNycz,是的,謝謝你告訴我,我會解決這個問題。 – mauve