简体   繁体   English

如何在std :: tr1 :: weak_ptr的容器上使用std :: remove?

[英]How can I use std::remove on a container with std::tr1::weak_ptr?

If I had a STL container, say a list of pointers I could remove them like in the exmple below. 如果我有一个STL容器,说一个指针列表,我可以删除它们,如下面的例子。 With a container of weak_ptrs this does not work, because they cannot be compared, as they need to be locked first. 使用weak_ptrs容器时,这不起作用,因为它们无法进行比较,因为它们需要先锁定。 What can I do? 我能做什么?

void MyClass::RemoveItem(std::tr1::weak_ptr<Item> const & pItem)
{
    mylist.remove(pItem);
}

For one thing, you could just define operator == for any weak_ptr. 首先,您可以为任何weak_ptr定义operator ==。 I'm sure there's a reason this is not implemented, it can probably bite you at a later point. 我确定这是没有实施的原因,它可能会在以后咬你。

template <typename T>
bool operator == (const std::tr1::weak_ptr<T>& a, const std::tr1::weak_ptr<T>& b)
{
    return a.lock() == b.lock();
}

... and you'll be able to just call remove() as usual. ...你可以像往常一样调用remove()。 This is a little bit extreme I guess. 我猜这有点极端。

If you stick to the remove_if() approach, you could get rid of the bind magic* by using function object: 如果你坚持使用remove_if()方法,你可以通过使用函数对象摆脱绑定魔术*:

struct EqPredicate
{
    const boost::weak_ptr<Item>& theItem;

    EqPredicate(const boost::weak_ptr<Item>& item) : theItem(item) 
    {
    }

    bool operator () (const boost::weak_ptr<Item>& p) const 
    { 
        return p.lock() == theItem.lock(); 
    }
};

and then use it like this: 然后像这样使用它:

mylist.remove_if(EqPredicate(pItem));

It looks like more code, but you can compress the EqPredicate class, it's mostly hollow. 它看起来像更多的代码,但你可以压缩EqPredicate类,它几乎是空洞的。 Also, it could be made template to use it with lists containing types other than Item. 此外,它可以作为模板使用它与包含除Item之外的类型的列表。

Oh, and do pass you weak_ptrs by reference everywhere including your comparison function. 哦,并且通过引用传递给你weak_ptrs包括你的比较函数。

*bind is not free performance-wise. * bind不是免费的性能。 If you expect a lot of Remove() calls and care much about performance it might be good to avoid it. 如果您期望大量的Remove()调用并且非常关注性能,那么避免它可能会很好。

I think the problem with sbk's approach is the weak_ptr operator== has the potential for a race. 我认为sbk方法的问题是weak_ptr运算符==具有竞争的潜力。 There's no guarantee of a shared_ptr to a or b existing even as you return from operator==, which makes it easy to misinterpret the resulting code. 即使从operator ==返回,也不能保证a或b存在shared_ptr,这使得很容易误解结果代码。

With it, it seems the best you could do is: 有了它,你可以做的最好的事情是:

if(a == b) {
  boost::shared_ptr<Item> a_locked(a.lock());
  boost::shared_ptr<Item> b_locked(b.lock());
  // It is an error to assume a_locked == b_locked here
  // It is an error to assume a.lock() == b.lock() here
  // It is an error to assume a.get() or b.get() here
}

which is not that useful. 哪个没用。 Now, if you were iterating over a container, you could still remove the iterators at this point, but there are many more cases where you would have ended up making just slightly the wrong comparison. 现在,如果你在一个容器上进行迭代,你仍然可以在这一点上删除迭代器,但是还有更多的情况你最终只会稍微做出错误的比较。

Just because I searched like forever to find the answer. 只因为我一直在寻找答案。

Create a function to compare the weak_ptrs and then bind one argument. 创建一个函数来比较weak_ptrs然后绑定一个参数。

    bool weak_ptr_comparsion(Item::wPtr  a, Item::wPtr  b)
    {
        return a.lock() == b.lock();
    }

    void MyClass::RemoveItem(Item::wPtr const & pItem)
    {
        mylist.remove_if(std::tr1::bind(weak_ptr_comparsion, pItem, 
                         std::tr1::placeholders::_1));
    }

Dont forget to include <tr1/functional> 别忘了包含<tr1/functional>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM