Date: Wed, 10 Jul 2024 23:13:57 +0100
People complain about the performance of 'dynamic_cast'.
Starting out with the following class hierarchy:
struct Base { virtual ~Base(void) = default; };
struct Derived : Base {};
struct MostDerived : Derived {};
And let's say we have defined just one variable:
MostDerived var;
And let's say we have a pointer to its base:
Base *p = &var;
Now let's say we have a standard library function something like:
namespace std {
template<class Dst, class Src>
ptrdiff_f dynamic_cast_offset(type_info const &most_derived);
}
We would call this function to cache the offset for a 'MostDerived' object:
ptrdiff_t offset = dynamic_cast_offset<Derived,Base>(typeid(MostDerived));
And so then instead of doing:
Derived *pd = dynamic_cast<Derived*>(p);
We would do:
if ( typeid(*p) == typeid(MostDerived) ) pd = p + offset;
This could be an optimisation used for example in a function that 9
times out of 10 deals with the same most-derived type. Or even if
there are 3 commonly used types, we could do an if-else ladder:
if ( typeid(*p) == typeid(MostDerived) ) pd = p + offset;
else if ( typeid(*p) == typeid(MostDerived2) ) pd = p + offset2;
else if ( typeid(*p) == typeid(MostDerived3) ) pd = p + offset3;
else pd = dynamic_cast<Derived*>(p);
Starting out with the following class hierarchy:
struct Base { virtual ~Base(void) = default; };
struct Derived : Base {};
struct MostDerived : Derived {};
And let's say we have defined just one variable:
MostDerived var;
And let's say we have a pointer to its base:
Base *p = &var;
Now let's say we have a standard library function something like:
namespace std {
template<class Dst, class Src>
ptrdiff_f dynamic_cast_offset(type_info const &most_derived);
}
We would call this function to cache the offset for a 'MostDerived' object:
ptrdiff_t offset = dynamic_cast_offset<Derived,Base>(typeid(MostDerived));
And so then instead of doing:
Derived *pd = dynamic_cast<Derived*>(p);
We would do:
if ( typeid(*p) == typeid(MostDerived) ) pd = p + offset;
This could be an optimisation used for example in a function that 9
times out of 10 deals with the same most-derived type. Or even if
there are 3 commonly used types, we could do an if-else ladder:
if ( typeid(*p) == typeid(MostDerived) ) pd = p + offset;
else if ( typeid(*p) == typeid(MostDerived2) ) pd = p + offset2;
else if ( typeid(*p) == typeid(MostDerived3) ) pd = p + offset3;
else pd = dynamic_cast<Derived*>(p);
Received on 2024-07-10 22:14:10