STL コンテナーがある場合、以下の例のように削除できるポインターのリストを言います。最初にロックする必要があるため、weak_ptrs のコンテナーでは比較できないため、これは機能しません。私に何ができる?
void MyClass::RemoveItem(std::tr1::weak_ptr<Item> const & pItem)
{
mylist.remove(pItem);
}
1 つには、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 クラスを圧縮できます。ほとんどが中空です。また、アイテム以外のタイプを含むリストで使用するためのテンプレートにすることもできます。
ああ、あなたの比較関数を含むどこでも参照によってweak_ptrsを渡します。
*bind は性能的に無料ではありません。多くの Remove() 呼び出しが予想され、パフォーマンスを重視する場合は、それを避けるのが良いかもしれません。
sbkのアプローチの問題は、weak_ptroperator==にレースの可能性があることだと思います。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
}
これはあまり役に立ちません。さて、コンテナを反復処理している場合でも、この時点でイテレータを削除することはできますが、わずかに間違った比較を行ってしまう場合がさらに多くあります。
答えを見つけるために永遠に検索したからです。
weak_ptrs を比較する関数を作成し、1 つの引数をバインドします。
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>