tags:

views:

263

answers:

2

If I had a STL container, say a list of pointers I could remove them like in the exmple below. With a container of weak_ptrs this does not work, because they cannot be compared, as they need to be locked first. What can I do?

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

Just because I searched like forever to find the answer.

Create a function to compare the weak_ptrs and then bind one argument.

    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>

nasmorn
Seems like you should use a function object instead, and take parameters by reference.
rlbond
+4  A: 

For one thing, you could just define operator == for any weak_ptr. 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. 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:

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. Also, it could be made template to use it with lists containing types other than Item.

Oh, and do pass you weak_ptrs by reference everywhere including your comparison function.

*bind is not free performance-wise. If you expect a lot of Remove() calls and care much about performance it might be good to avoid it.

sbk