【问题标题】:How can I use a std::map with std::weak_ptr as key?如何使用 std::map 和 std::weak_ptr 作为键?
【发布时间】:2012-10-04 05:57:13
【问题描述】:

如何使用std::weak_ptr 作为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&lt; 有关。我需要为weak_ptr 定义operator&lt; 吗?确切地说,需要定义哪些运算符才能将数据类型用作std::map 的键?

(我应该注意到我已经在std 命名空间中定义了operator==。另外,我计划将weak_ptr 用于自定义类类型,而不是int。)

【问题讨论】:

  • 指向具有相同值的不同int对象的指针应该相等还是不同? IE。 auto first = std::make_shared(5); auto second = std::make_shared(5); myMap[first] = true; myMap[second] = false; 应该有多少元素?

标签: c++ dictionary stdmap weak-references weak-ptr


【解决方案1】:

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

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

【讨论】:

  • 最终形式为std::map&lt;std::weak_ptr&lt;T&gt;, U, std::owner_less&lt;std::weak_ptr&lt;T&gt;&gt;&gt;
【解决方案2】:

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

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;

如果您打算将weak_ptr 用于自定义类而不是int,则只需将int 替换为您的类名称,如this example code on Coliru 所示。

一般来说,除了为(自定义)键类型提供适当的比较函数(或重载operator&lt;)外,无需为std::map 做任何事情。不需要为密钥类型重载 operator==

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 2011-06-23
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 2016-08-03
    相关资源
    最近更新 更多