I understand that using static_pointer_cast
with unique_ptr
would lead to a shared ownership of the contained data.
In other terms, what I'd like to do is:
unique_ptr<Base> foo = fooFactory(); // do something for a while unique_ptr<Derived> bar = static_unique_pointer_cast<Derived>(foo);
Anyway doing that results with two unique_ptr
that should never exist at the same time, so it is simply forbidden.
Right, it makes sense, absolutely, that's why there doesn't exist anything like static_unique_pointer_cast
indeed.
So far, in cases where I want to store pointers to those base classes, but I also need to cast them to some derived classes (as an example, imagine a scenario involving type erasure), I've used shared_ptr
s because of what I've above mentioned.
Anyway, I was guessing if there are alternatives to shared_ptr
s for such a problem or if they are really the best solution in that case.
In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.
A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.
It can be assigned: class owner { std::unique_ptr<someObject> owned; public: owner() { owned=std::unique_ptr<someObject>(new someObject()); } };
One of the thing the library doesn't provide is a way to cast std::unique_ptr , for example, from a base type to a derived type. You can see the code in action on ideone.com. Note As noted in a prior comment section, this code is not safe to temporarily cast the pointer.
#Raw pointers
The solution for your problem is to get the raw (non-owning) pointer and cast it - then just let the raw pointer go out of scope and let the remaining unique_ptr<Base>
control the lifetime of the owned object.
Like this:
unique_ptr<Base> foo = fooFactory(); { Base* tempBase = foo.get(); Derived* tempDerived = static_cast<Derived*>(tempBase); } // tempBase and tempDerived go out of scope here, but foo remains -> no need to delete
#Unique_pointer_cast The other option is to use the release()
function of unique_ptr
to wrap it into another unique_ptr.
Like this:
template<typename TO, typename FROM> unique_ptr<TO> static_unique_pointer_cast (unique_ptr<FROM>&& old){ return unique_ptr<TO>{static_cast<TO*>(old.release())}; // conversion: unique_ptr<FROM>->FROM*->TO*->unique_ptr<TO> } unique_ptr<Base> foo = fooFactory(); unique_ptr<Derived> foo2 = static_unique_pointer_cast<Derived>(std::move(foo));
Remember that this invalidates the old pointer foo
#Reference from raw pointers Just for completeness of the answer, this solution was actually proposed as a small modification of the raw pointers by the OP in the comments.
Similar to using raw pointers one can cast the raw pointers and then create a reference out of them by derefering. In this case it is important to guarantee that the lifetime of the created reference does not exceed the lifetime of the unique_ptr.
Sample:
unique_ptr<Base> foo = fooFactory(); Derived& bar = *(static_cast<Derived*>(foo.get())); // do not use bar after foo goes out of scope
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With