19

如何将a 用作std::weak_ptra 的键,std::map如下面的代码所示?

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

错误消息似乎与operator<. 我需要定义operator<weak_ptr?确切地说,需要定义哪些运算符才能将数据类型用作 a 的键std::map

(我应该注意我已经operator==std命名空间中定义了。另外,我打算使用weak_ptr自定义类类型而不是int.)

4

2 回答 2

30

C++11 提供了适当的比较机制std::weak_ptr,即:std::owner_less.

这应该是地图和集合的默认设置。如果您使用的 C++ 编译器遇到困难,请尝试使用std::owner_less它(如果可用)。如果它不可用,您将需要提供类似的机制,std::owner_less以便您可以适当地比较std::weak_ptr对象。

于 2012-10-13T18:36:29.937 回答
7

正如Jody Hagins 的回答中所解释的,如果您使用 a作为键,则应将std::owner_less其用作关联容器的比较函数对象。std::weak_ptr我想通过为您的代码提供以下完整解决方案来扩展该答案:

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

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

    myMap[weakptr] = true;

    return 0;
}

C++17开始,您可以省略 的模板参数owner_less,从而缩短代码,如下所示:

std::map<std::weak_ptr<int>, bool, std::owner_less<>> myMap;

如果您打算使用 aweak_ptr到自定义类而不是int,那么您可以简单地将 替换int为您的类的名称,如Coliru 上的示例代码所示

一般来说,除了operator<为(自定义)键类型提供适当的比较函数(或重载)之外,不需要为std::map. operator==不需要对密钥类型进行重载。

于 2019-09-17T08:36:35.090 回答