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

时间:2009-09-07 17:37:30

标签: c++ stl tr1

如果我有一个STL容器,请说出一个指针列表,我可以删除它们,如下面的示例所示。使用weak_ptrs容器时,这不起作用,因为它们无法进行比较,因为它们需要先锁定。我该怎么办?

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

3 个答案:

答案 0 :(得分:5)

首先,你可以为任何weak_ptr定义operator ==。我确定这是没有实施的原因,它可能会在以后咬你。

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

...你可以像往常一样调用remove()。我觉得这有点极端。

如果你坚持使用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(); 
    }
};

然后像这样使用它:

mylist.remove_if(EqPredicate(pItem));

它看起来像更多代码,但你可以压缩EqPredicate类,它几乎是空洞的。此外,可以将模板用于包含除Item之外的类型的列表。

哦,并且通过引用传递给你的weak_ptrs包括你的比较函数。

* bind在性能方面不是免费的。如果您期望进行大量的Remove()调用并且非常关注性能,那么最好避免它。

答案 1 :(得分:0)

因为我一直在寻找答案。

创建一个函数来比较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));
    }

别忘了包含<tr1/functional>

答案 2 :(得分:0)

我认为sbk方法的问题是weak_ptr运算符==具有竞争的潜力。即使从operator ==返回,也不能保证a或b存在shared_ptr,这样可以很容易地误解生成的代码。

有了它,你能做的最好就是:

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
}

没有那么有用。现在,如果你在一个容器上进行迭代,你仍然可以在这一点上删除迭代器,但是在更多的情况下,你最终会略微做出错误的比较。