C++ std::shared_ptr losing const的实例化类型

C++ std::shared_ptr losing const的实例化类型,c++,c++11,C++,C++11,鉴于以下计划: #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 )

鉴于以下计划:

#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>() );
}
#包括
模板
类SharedPtr:public std::shared\u ptr
{
typedef std::共享\u ptr Impl;
模板好友类SharedPtr;
SharedPtr(Impl const&other):Impl(other){}
公众:
SharedPtr(T*newed_ptr):Impl(newed_ptr){}
SharedPtr(SharedPtr const&other)throw():Impl(other){}
模板SharedPtr(SharedPtr const&other)throw():Impl(other){}
模板SharedPtr DynamicCast()常量throw()
{
返回SharedPtr(std::dynamic_pointer_cast(*this));
}
};
模板类句柄:publicsharedptr
{
typedef-SharedPtr-Base;
模板好友类句柄;
公众:
显式句柄(T const*pObject=0):基(pObject){}
句柄(SharedPtr const&src):基(src){}
模板
句柄(句柄常量和其他):基(其他){}
模板
句柄DynamicCast()常量throw(){
SharedPtr tmp=this->Base::template DynamicCast();
返回手柄(tmp);
}
};
类B{public:virtual~B(){};
D类:公共B{};
无效的
testit()
{
手柄p(新的D);
手柄p1(p);
句柄p2(p1.DynamicCast());
}
我得到以下错误(来自g++4.7.2):

noX.cc:SharedPtr::SharedPtr(constsharedptr&)[with U=constd;T=D]的实例化:
noX.cc | 33 col 37 |必须来自“Handle Handle::DynamicCast()const[with-Derived=D;T=B]”
noX.cc | 45 col 37 |此处需要
noX.cc | 13 col 88 |错误:调用“std::shared_ptr::shared_ptr(const SharedPtr&)”时没有匹配函数
noX.cc | 13 col 88 |注:候选人包括:
还有一长串的候选人。微软(MSVC 11)提供 类似的消息,因此我假设错误在我的代码中,并且 不是编译器错误

很明显,我不希望能够转换 a
SharedPtr
到a
SharedPtr
(或 a
std::shared_ptr
到a
std::shared_ptr
,即 微软的抱怨)。但是这家公司在哪里
SharedPtr
首先来自哪里?我什么也看不见 上面代码中应该创建的任何智能指针 非常量的任何类型。

模板类句柄:public SharedPtr
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 );
    }
{ 句柄(SharedPtr const&src):基(src){} 句柄DynamicCast()常量throw(){ SharedPtr tmp=this->Base::template DynamicCast(); 返回手柄(tmp); }

您的返回是
句柄
其中T的类型为
派生
而不包含常量。
SharedPtr
中的T的类型为
派生常量

乍一看,似乎是为
句柄(SharedPtr const&src)
调用
返回句柄(tmp)隐式创建了
SharedPtr
对象;

此构造函数:

Handle( SharedPtr<T> const& src ) : Base( src ) {}
您需要一个
SharedPtr
->
句柄
转换,尽管唯一可能的候选对象是采用
SharedPtr
的构造函数。一个解决方案是将其更改为:

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

如果需要,将隐式转换“移动”到调用者。

很好。我将
SharedPtr
构造函数更改为
Handle(SharedPtr const&src)
,示例代码现在可以编译了。(我必须看看这是否纠正了真实代码中的问题,但
SharedPtr
显然是一个错误。@LucDanton是的。这就是错误。我只是没有找准位置。另一个问题是你?你想用这些类实现什么?只是好奇…@Dilip提供了一个安全的函数式界面。它们是部分历史条件,但在实际代码中,它们当然要复杂得多。尤其是
模板
类SharedPtr
,具有部分专门化,因此
SharedPtr`的实际实现取决于指向类是否支持入侵引用计数(从长远来看,要摆脱无创参考计数,太危险了)。
return Handle<Derived>( tmp );
Handle(Base const& src ) : Base( src ) {}