Suppose we have the following code:
#include <memory>
#include <vector>
struct BaseComponent
{
template <typename T>
T * as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
int main()
{
std::vector<std::unique_ptr<BaseComponent>> mComponents;
mComponents.emplace_back(new PositionComponent);
auto *pos = mComponents[0]->as<PositionComponent>();
pos->x = 1337;
return 0;
}
In the T * as() method, should I use a static_cast or a dynamic_cast? are there times when the the conversion will fail? Do I need to dynamic_cast like this instead?
auto *ptr = dynamic_cast<T*>(this);
if(ptr == nullptr)
throw std::runtime_error("D'oh!");
return ptr;
In your case there is no way to tell statically whether this
is the right type or not.
What you may want is a CRTP (Curiously recurring template pattern):
template <class T>
struct BaseComponent
{
T* as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent<T>
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
This way you can do:
auto x = yourBaseComponent.as();
and have the right child type statically.
The code that you present is correct and well formed, but the cast in general is not safe. If the actual object was not a PositionComponent
, then the compiler would very gladly assume that it is and you would be causing undefined behavior.
If you replace the cast with dynamic_cast
, then the compiler will generate code that at runtime verifies that the conversion is valid.
The real question is why would you need this. There are reasons, but more often than not the use of casts are an indication of issues with your design. Reconsider whether you can do better (i.e. redesign your code so that you don't need to go explicitly converting types)
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