3

次のプログラムがあるとします。

#include <memory>

template <typename T>
class SharedPtr : public std::shared_ptr<T>
{
    typedef std::shared_ptr<T> Impl;
    template<typename U> friend class SharedPtr;
    SharedPtr( Impl const& other ) : Impl( other ) {}
public:
    SharedPtr( T* newed_ptr ) : Impl( newed_ptr ) {}
    SharedPtr( SharedPtr const& other ) throw() : Impl( other ) {}
    template <typename U> SharedPtr( SharedPtr<U> const& other ) throw() : Impl( other ) {}

    template <typename U> SharedPtr<U> DynamicCast() const throw()
    {
        return SharedPtr<U>( std::dynamic_pointer_cast<U>( *this ) );
    }
};

template<typename T> class Handle : public SharedPtr<T const>
{
    typedef SharedPtr<T const> Base;
    template <typename U> friend class Handle;
public:
    explicit Handle( T const* pObject = 0 ) : Base( pObject ) {}
    Handle( SharedPtr<T> const& src ) : Base( src ) {}
    template <typename Derived>
    Handle( Handle<Derived> const& other ) : Base( other ) {}
    template <typename Derived>
    Handle<Derived> DynamicCast() const throw() {
        SharedPtr<Derived const> tmp = this->Base::template DynamicCast<Derived const>();
        return Handle<Derived>( tmp );
    }
};

class B { public: virtual ~B() {} };
class D : public B{};

void
testit()
{
    Handle<D> p( new D );
    Handle<B> p1( p );
    Handle<D> p2( p1.DynamicCast<D>() );
}

次のエラーが表示されます (g++ 4.7.2 から):

noX.cc: In instantiation of ‘SharedPtr<T>::SharedPtr(const SharedPtr<U>&) [with U = const D; T = D]’:
noX.cc|33 col 37| required from ‘Handle<Derived> Handle<T>::DynamicCast() const [with Derived = D; T = B]’
noX.cc|45 col 37| required from here
noX.cc|13 col 88| error: no matching function for call to ‘std::shared_ptr<D>::shared_ptr(const SharedPtr<const D>&)’
noX.cc|13 col 88| note: candidates are:

そして候補者の長いリスト。Microsoft (MSVC 11) も同様のメッセージを表示するため、エラーはコンパイラ エラーではなくコードにあると想定しています。

SharedPtr<D const>明らかに、aを a にSharedPtr<D>(または astd::shared_ptr<D const>をaに変換できるとは思っていませんstd::shared_ptr<D>。Microsoft はこれについて不満を述べています)。しかし、 SharedPtr<D>そもそもどこから来るのでしょうか? 上記のコードには、任意の型の非 const へのスマート ポインターを作成する必要があるものは何も表示されません。

4

3 に答える 3

4

このコンストラクタ:

Handle( SharedPtr<T> const& src ) : Base( src ) {}

SharedPtr<T>からへの暗黙的な変換SharedPtr<T const>(つまり) に依存していBaseます。しかし、ここで:

return Handle<Derived>( tmp );

SharedPtr<T const>->変換が必要ですHandle<T>が、可能性のある唯一の候補はコンストラクターの取得SharedPtr<T>です。1 つの解決策は、次のように変更することです。

Handle(Base const& src ) : Base( src ) {}

必要に応じて、暗黙的な変換を呼び出し元に「移動」します。

于 2013-05-23T15:23:53.640 に答える
3
template<typename T> class Handle : public SharedPtr<T const>
{
    Handle( SharedPtr<T> const& src ) : Base( src ) {}

    Handle<Derived> DynamicCast() const throw() {
        SharedPtr<Derived const> tmp = this->Base::template DynamicCast<Derived const>();
        return Handle<Derived>( tmp );
    }

HandleT がDerivedconst なしの型である a を返します。T inSharedPtr<T>はタイプDerived constですが。

于 2013-05-23T15:19:45.403 に答える
3

一見すると、オブジェクトが呼び出しSharedPtr<Derived>用に暗黙的に作成されているように見えますHandle( SharedPtr<T> const& src )return Handle<Derived>( tmp );

于 2013-05-23T15:20:29.960 に答える