私の質問shared_ptr
は、バグが含まれていると思われるGCC4.7.2での代入演算子テンプレートの実装に関するものです。
前提1:C++11標準
これが私が話している代入演算子テンプレートの署名です:
template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
C ++ 11標準(20.7.2.2.3)から:
「に相当し shared_ptr(r).swap(*this)
ます。」
つまり、代入演算子テンプレートはコンストラクターテンプレートで定義されます。コンストラクターテンプレートの署名は次のとおりです。
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
C ++ 11標準(20.7.2.2.1)から:
「必要条件:Y*が暗黙的にT*に変換可能でない限り、[...]コンストラクターはオーバーロード解決に参加してはなりません。」
前提2:GCC 4.7.2の実装:
これで、GCC 4.7.2のコンストラクターテンプレートの実装は私には正しいように見えます(std::__shared_ptr
の基本クラスですstd::shared_ptr
):
template<typename _Tp1, typename =
typename std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
:
_M_ptr(__r._M_ptr),
_M_refcount()
{
_M_refcount._M_swap(__r._M_refcount);
__r._M_ptr = 0;
}
ただし、GCC4.7.2の代入演算子テンプレートの実装は次のとおりです。
template<typename _Tp1>
__shared_ptr& operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
return *this;
}
私が驚いたのは、この操作がコンストラクターテンプレートや。の観点から定義されていないswap()
ことです。特に、単純な割り当てでは、型との変換可能性が明示的にチェックされている_M_ptr = __r._M_ptr
場合と同じ結果は得られません(これは特殊化できます)。_Tp1*
_Tp*
std::is_convertible
前提3:VC10の実装
私は、VC10がこの点でより適合した実装を持っていることに気づきました。これは正しいと考えており、テストケースで期待どおりに動作します(GCCはそうではありません)。
template<class _Ty2>
_Myt& operator=(const shared_ptr<_Ty2>& _Right)
{
// assign shared ownership of resource owned by _Right
shared_ptr(_Right).swap(*this);
return (*this);
}
質問:
GCC 4.7.2の実装に実際にバグはありshared_ptr
ますか?この問題のバグレポートは見つかりませんでした。
ポストスクリプト:
私のテストケースが何であるか、なぜ私がこの一見重要でない詳細を気にするのか、そしてなぜ私が専門にする必要があることを暗示しているように見えるのかを私に尋ねたい場合は、std::is_convertible
チャットでそうしてください。それは長い話であり、誤解されることなくそれを要約する方法はありません(その不快な結果のすべてを伴う)。前もって感謝します。