In this answer, the following scenario came up:
#include <cassert>
struct A {};
struct B { virtual ~B(){} };
struct AA{};
template <class T>
struct C : A, T {};
int main()
{
  B * b = new C<B>;
  AA * aa = new C<AA>;
  assert(dynamic_cast<A*>(b));
  assert(dynamic_cast<A*>(aa)); //this line doesn't compile, as expected
}
On g++ 4.8.4 (Ubuntu), this compiles and the assert passes.  My question is, is that really legal?  I feel like you shouldn't be able to dynamic_cast to a non-polymorphic class at all, but I freely admit that I'm not an expert in what's happening here.
When I tried the opposite direction:
dynamic_cast<B*>((A*)(new C<B>));
it fails to compile, stating that "source type is not polymorphic". I feel like that's a clue, but it still seems a stretch to find the non-polymorphic base class that belongs to a class that the current pointer is a base of (did that sentence make sense?).
Yes, you can.
As the C++ standard says in §5.2.7/5 about the expression dynamic_cast<T>(v):
If
Tis “pointer to cv1B” andvhas type “pointer to cv2D” such thatBis a base class ofD, the result is a pointer to the uniqueBsubobject of theDobject pointed to byv.
An example is given, too:
struct B { }; struct D : B { }; void foo(D* dp) { B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp; }
As you can see, polymorphic classes are clearly not the only use case of dynamic_cast permitted by the standard.
By the way, cppreference explains it in less standardese language:
If new_type is a pointer or reference to Base, and the type of expression is a pointer or reference to Derived, where Base is a unique, accessible base class of Derived, the result is a pointer or reference to the Base class subobject within the Derived object pointed or identified by expression. (Note: an implicit cast and static_cast can perform this conversion as well.)
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