简体   繁体   中英

auto_ptr and dynamic_pointer_cast

If I wish to use dynamic_cast with a shared_ptr I can use dynamic_pointer_cast . What do I use if I wish to cast an auto_ptr ? I'm assuming something that would look like below.

struct B : A { };
...
auto_ptr<A> base( ... );
auto_ptr<B> derive = dynamic_pointer_cast<B>(base);

I'm using boost for shared_ptr's

auto_ptr<A> base( ... );
if(B* query = dynamic_cast<B>(base.get())) {
    // take ownership
    base.release();
    auto_ptr<B> derived(query);

    // use and/or pass derived around here
    // ...
} else {
    // no dice: leave base as owner
}

Since you're already doing that, then refactor it, slap it in the namespace of your choice and call it a day:

// Postcondition:
// where r is the returned pointer and p == from.get()
// EITHER r == 0 AND from.get() == p
// OR r.get() == dynamic_cast<To>(p) AND from == 0
template<typename To, typename From>
std::auto_ptr<To>
dynamic_pointer_cast(std::auto_ptr<From>& from)
{
    To* query = dynamic_cast<To>(from.get());
    return query ? from.release(), query : 0;
}

By the nature of auto_ptr (which you should never use. Or if you have to use it, never copy-construct or copy-assign it), copying is equivalent to moving. Therefore, there is no way to do a cast without transferring ownership, which causes the previous owner to lose ownership.

And what would happen if it returned an empty auto_ptr (meaning a failed dynamic_cast )? The original owner of the pointer has lost ownership, thanks to the cast. The new owner doesn't have the pointer, since the cast failed. So who would own it?

I'm sure you can partially specialize dynamic_pointer_cast for any pointer type you want however.

Also, auto_ptr is deprecated in C++0x; the standards committee isn't going to promote the use of deprecated functionality by making dynamic_pointer_cast work with it..

It would go like this:

auto_ptr<Derived> pd(
    dynamic_cast<Derived*>( base.get() )? static_cast<Derived*>( base.release() ) : 0
    );

Then check whether an ownership transfer did occur.

If it didn't, you might reset the original auto_ptr , and throw an exception.

Since especially Microsoft's implementation of auto_ptr has been very shaky, and probably still is, it's important to not rely on the conversions guaranteed by the standard.

Cheers & hth.,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM