2つのstd::weak_ptrまたは1つのstd::weak_ptrと1つのstd::shared_ptrを比較して同等性を確認します。
私が知りたいのは、weak_ptr/shared_ptrのそれぞれが指すオブジェクトが同じであるかどうかです。アドレスが一致しない場合だけでなく、基になるオブジェクトが削除されてから偶然同じアドレスで再構築された場合も、比較によって否定的な結果が得られるはずです。
したがって、基本的に、アロケータが同じアドレスを予約している場合でも、このアサーションを保持する必要があります。
auto s1 = std::make_shared<int>(43);
std::weak_ptr<int> w1(s1);
s1.reset();
auto s2 = std::make_shared<int>(41);
std::weak_ptr<int> w2(s2);
assert(!equals(w1,w2));
weak_ptrテンプレートは等式演算子を提供しません、そして私が理解したように、それは正当な理由です。
したがって、単純な実装は次のようになります。
template <typename T, typename U>
inline bool naive_equals(const std::weak_ptr<T>& t, const std::weak_ptr<U>& u)
{
return !t.expired() && t.lock() == u.lock();
}
template <typename T, typename U>
inline bool naive_equals(const std::weak_ptr<T>& t, const std::shared_ptr<U>& u)
{
return !t.expired() && t.lock() == u;
}
その間に最初のweak_ptrが期限切れになった場合、0になります。そうでない場合は、weak_ptrをshared_ptrにアップグレードし、アドレスを比較します。
これに伴う問題は、weak_ptrを2回(1回)ロックする必要があることです!時間がかかりすぎるのではないかと思います。
私はこれを思いついた:
template <typename T, typename U>
inline bool equals(const std::weak_ptr<T>& t, const std::weak_ptr<U>& u)
{
return !t.owner_before(u) && !u.owner_before(t);
}
template <typename T, typename U>
inline bool equals(const std::weak_ptr<T>& t, const std::shared_ptr<U>& u)
{
return !t.owner_before(u) && !u.owner_before(t);
}
これは、uの所有者ブロックがtの「前」ではなく、tがuの前ではないかどうかをチェックするため、t==uです。
これは私が意図したとおりに機能しますか?別個のshared_ptrから作成された2つのweak_ptrは、常にこのように等しくないものとして比較されますか?それとも私は何かを逃しましたか?
編集:なぜ私はそもそもこれをしたいのですか?共有ポインターを含むコンテナーが必要であり、その中のオブジェクトへの参照を配布したいと思います。イテレータは無効になっている可能性があるため、使用できません。(整数の)IDを配布することはできますが、それは一意性の問題につながり、マップタイプが必要になり、検索/挿入/削除操作が複雑になります。アイデアは、std :: setを使用し、ポインター自体(ラッパークラスにカプセル化されている)をキーとして提供することです。これにより、クライアントはweak_ptrを使用してセット内のオブジェクトにアクセスできます。