“下转换” unique_ptr< Base>到unique_ptr< Derived> [英] "Downcasting" unique_ptr<Base> to unique_ptr<Derived>

查看:154
本文介绍了“下转换” unique_ptr< Base>到unique_ptr< Derived>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一系列工厂会返回 unique_ptr< Base> 。在引擎盖下,它们提供了指向各种派生类型的指针,即 unique_ptr< Derived> unique_ptr< DerivedA> unique_ptr< DerivedB> 等。



给定 DerivedA:Derived Derived:Base 我们会有:

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

我需要做的是 code> unique_ptr< Base> 到一些派生级别(不一定是原来的内部级别)。以伪代码说明:

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

我想通过从 unique_ptr ,然后使用一个函数,该函数强制转换原始指针并将其重新分配给所需风格的另一个 unique_ptr code>将在调用之前由调用者显式地完成):

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

这是有效的,还是会有一些有趣的事情? / p>




有一个额外的复杂性,一些工厂驻留在动态加载在运行时的DLL,这意味着我需要确保生产的对象在同一上下文(堆空间)中被销毁,因为他们被创建。所有权的转移(通常发生在另一个上下文中)然后必须从原始上下文提供删除器。但除了必须连同指针一起提供/投放一个删除器之外,投射问题应该是一样的。

解决方案

p>我会创建几个函数模板, static_unique_ptr_cast dynamic_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 从呼叫者脚下划出


I have a series of factories that return unique_ptr<Base>. Under the hood, though, they are providing pointers to various derived types, i.e unique_ptr<Derived>, unique_ptr<DerivedA>, unique_ptr<DerivedB>etc.

Given DerivedA : Derived and Derived : Base we'd have:

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

What I need to do is to "cast" the pointer from the returned unique_ptr<Base> to some derived level (not necessarily the original internal one). To illustrate in pseudo code:

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

I'm thinking of doing this by releasing the object from the unique_ptr, then using a function that casts the raw pointer and reassigns that to another unique_ptr of the desired flavor (the release would be explicitly done by the caller prior to the call):

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

Is this valid, or is / will there be something funky going on?


PS. There is an added complication in that some of the factories reside in DLLs that are dynamically loaded at run-time, which means I need to make sure the produced objects are destroyed in the same context (heap space) as they were created. The transfer of ownership (which typically happens in another context) must then supply a deleter from the original context. But aside from having to supply / cast a deleter along with the pointer, the casting problem should be the same.

解决方案

I'd create a couple of function templates, static_unique_ptr_cast and dynamic_unique_ptr_cast. Use the former in cases where you're absolutely certain the pointer is actually a Derived *, otherwise use the latter.

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());
}

The functions are taking an rvalue reference to ensure that you're not pulling the rug out from underneath the caller's feet by stealing the unique_ptr passed to you.

这篇关于“下转换” unique_ptr&lt; Base&gt;到unique_ptr&lt; Derived&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆