I have some code with a generic interface in which I need to cast up and down. I'm trying to convert to smart pointers now, but am running into some errors. The code below reproduces the problem. I'm using C++14, so I think this stuff is supposed to work automagically now?
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> a(new int);
*a = 5;
std::shared_ptr<void> b = std::dynamic_pointer_cast<void>(a);
std::shared_ptr<int> c = std::dynamic_pointer_cast<int>(b);
std::cout << *c; //should be 5
return 0;
}
However, when I try to compile this, I get:
Error C2680 '_Elem1 *': invalid target type for dynamic_cast
Error C2681 'int *': invalid expression type for dynamic_cast
Guessing I did something dumb in the syntax?
A pointer (or reference) to a class can actually point (refer) to any class derived from that class. Occasionally, it may be desirable to obtain a pointer to the fully derived class, or to some other subobject of the complete object. The dynamic cast provides this facility.
Upcasting can cause object slicing when a derived class object is passed by value as a base class object, as in foo(Base derived_obj). The opposite process, converting a base-class pointer (reference) to a derived-class pointer (reference) is called downcasting. Downcasting is not allowed without an explicit type cast.
Static casting is done by the compiler: it treats the result as the target type, no matter what. You do this when you're absolutely sure about the argument being of the target type. Dynamic casting is done at runtime, and thus requires runtime type information.
A dynamic cast expression is used to cast a base class pointer to a derived class pointer. This is referred to as downcasting.
The rules are the same as for dumb pointers, except you have to use std::static_pointer_cast
and std::dynamic_pointer_cast
instead of static_cast
and dynamic_cast
. C++17 will introduce the counterpart for reinterpret_cast
, but that is not needed for up- or down casts, nor for conversions from or to void.
How do I dynamic upcast ... with smart pointers?
Conversion up in type hierarchy is implicit, so there is no need for a cast:
struct A{
virtual ~A(){}
};
struct B:A{};
auto b = std::make_shared<B>();
std::shared_ptr<A> a = b;
How do I dynamic ... downcast with smart pointers?
Using std::dynamic_pointer_cast
if you're unsure whether the source points to the correct type. This is only possible if the inheritance is polymorphic (i.e. the base has at least one virtual function):
b = std::dynamic_pointer_cast<B>(a);
Or std::static_pointer_cast
if you know that the type is correct:
b = std::static_pointer_cast<B>(a);
std::shared_ptr<void> b = std::dynamic_pointer_cast<void>(a); std::shared_ptr<int> c = std::dynamic_pointer_cast<int>(b);
void
and int
do not have an inheritance relationship so they can not be up- or down casted.
However, all pointers are implicitly convertible to a void pointer, so an implicit conversion is possible:
std::shared_ptr<void> b = a;
And, void pointers can be static casted to the original type, so you can use std::static_pointer_cast
:
std::shared_ptr<int> c = std::static_pointer_cast<int>(b);
Since C++17, you have std::reinterpret_pointer_cast
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