2012-10-13 127 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