“downcasting”unique_ptr <Base>到unique_ptr <Derived>

我有一系列返回unique_ptr<Base>的工厂。 然而,它们提供了指向各种派生types的指针,即unique_ptr<Derived>unique_ptr<DerivedA>unique_ptr<DerivedB>等。

鉴于DerivedA : DerivedDerived : Base我们会有:

 unique_ptr<Base> DerivedAFactory() { return unique_ptr<Base>(new DerivedA); } 

我需要做的就是将指针从返回的unique_ptr<Base>到某个派生级别(不一定是原来的内部级别)。 为了说明伪代码:

 unique_ptr<Derived> ptr = static_cast<unique_ptr<Derived>>(DerivedAFactory()); 

我正在考虑通过从unique_ptr释放对象,然后使用一个函数来转换原始指针并将其重新分配给另一个所需flavor的unique_ptrrelease将在调用之前由调用方明确完成):

 unique_ptr<Derived> CastToDerived(Base* obj) { return unique_ptr<Derived>(static_cast<Derived*>(obj)); } 

这是有效的,还是会有一些质朴的事情呢?


PS。 还有一个复杂的问题,一些工厂驻留在运行时dynamic加载的DLL中,这意味着我需要确保生成的对象在创build时在相同的上下文(堆空间)中被销毁。 所有权的转移(通常发生在另一个环境中)必须从原始上下文中提供一个删除者。 但是除了必须提供/删除指针以外,投射问题应该是相同的。

我创build了几个函数模板, static_unique_ptr_castdynamic_unique_ptr_cast 。 使用前者的情况下,你绝对肯定指针实际上是Derived * ,否则使用后者。

 template<typename Derived, typename Base, typename Del> std::unique_ptr<Derived, Del> static_unique_ptr_cast( std::unique_ptr<Base, Del>&& p ) { auto d = static_cast<Derived *>(p.release()); return std::unique_ptr<Derived, Del>(d, std::move(p.get_deleter())); } template<typename Derived, typename Base, typename Del> std::unique_ptr<Derived, Del> dynamic_unique_ptr_cast( std::unique_ptr<Base, Del>&& p ) { if(Derived *result = dynamic_cast<Derived *>(p.get())) { p.release(); return std::unique_ptr<Derived, Del>(result, std::move(p.get_deleter())); } return std::unique_ptr<Derived, Del>(nullptr, p.get_deleter()); } 

这些函数采用右值引用,以确保您不会通过窃取传递给您的unique_ptr从呼叫者的脚下拖出地毯。