如何从 shared_ptr 上键入的 unordered_set 获取基于 raw_ptr 的元素

How to get an element based on raw_ptr from an unordered_set keyed on shared_ptr

我想知道我是否可以根据 shared_ptr 键控的 unordered_set 的原始指针检索元素。

unordered_set< shared_ptr<MyObj> > sets;
auto myobj = make_shared<MyObj>();
sets.insert(myobj);

// Find the element myobj
sets.find(myobj);

// How to find the element based on the underlying raw pointer?
sets.find(my.obj.get()); <---- apparently this gives compile error

// This method works but it will double free myobj though (not correct)
sets.find(shared_ptr<MyObj>(my.obj.get()));

您可以将 MyObj 声明为:

class MyObj : public std::enable_shared_from_this<MyObj>
{
     ....
}

这添加了一个返回给定对象实例的共享指针的方法。

MyObj * rawptr = myobj.get();
sets.find(rawptr->shared_from_this());

请注意,在对象上调用 shared_from_this() 之前,必须有一个 std::shared_ptr 拥有它。

要仅使用底层原始指针查找您要查找的内容,可以通过使用 std::set 和异构查找来完成。

这里需要注意的是,您必须使用集合而不是 unordered_set。如果您确实需要无序(我发现这种情况很少见),那么请使用 alexm 的 shared_from_this() 解决方案。否则异构查找是一种相当优雅和灵活的方法。

--

使用异构查找,您只需定义一个特殊的比较器,该集合将用于其排序功能。

以下应该可以解决问题:

struct Raw_comp{
  using is_transparent = std::true_type;
  bool operator()(const shared_ptr<MyObj>& lhs, const shared_ptr<MyObj>& rhs) const{
   return lhs < rhs;
}
  bool operator()(shared_ptr<MyObj>& lhs, MyObj* rhs) const{
   return std::less<MyObj>()(lhs.get(), rhs);
}
  bool operator()(const MyObj* lhs, const shared_ptr<MyObj>& rhs) const{
   return std::less<MyObj>()(lhs, rhs.get());
}
};

然后声明集合:

set< shared_ptr<myObj>, Raw_cmp> sets;

Here is more information on heterogeneous lookup if you are interested