Дано: контейнер примерно такого вида:
std::list< boost::weak_ptr<Item> > items;
Вместо %%boost::weak_ptr<>%% могу быть:
- %%std::tr1::weak_ptr<>%%
- %%std::weak_ptr<>%% для C++11
Задача: нужно удалить элемент по значению.
Казалось бы, просто сделай:
...
items.remove(value);
...
ан нет: для %%weak_ptr<>%% не определён оператор сравнения. Если потеоретизировать, можно предположить, почему так сделано: что бы гарантировать консистентность указателей при сравнении нужно их захватить (сделать %%value.lock()%%), т.е. создать два %%shared_ptr%% и уже их сравнивать, т.е. лишние накладные расходы.
Поэтому удаление можно делать так:
template <typename T>
bool operator == (const boost::weak_ptr<T>& a, const boost::weak_ptr<T>& b)
{
return a.lock() == b.lock();
}
после такого %%std::list::remove(const T&)%% будет работать для всех типов. Можно и сузить до конкретного.
Либо использовать %%std::list::remove_if(Predicate)%%, предикат объявить как:
struct EqPredicate
{
const boost::weak_ptr<Item>& item;
EqPredicate(const boost::weak_ptr<Item>& item)
: item(item)
{
}
bool operator () (const boost::weak_ptr<Item>& p) const
{
return p.lock() == item.lock();
}
};
и использовать так:
std::list< boost::weak_ptr<Item> > items;
...
items.remove_if(EqPredicate(value));
Информация взята отсюда: http://stackoverflow.com/questions/1390340/how-can-i-use-stdremove-on-a-container-with-stdtr1weak-ptr
Вышесказанное верно для %%boost::weak_ptr%%, %%std::tr1::weak_ptr%%, %%std::weak_ptr%%