I've just seen a code containing dynamic_cast from std::exception to std::nested_exception, for instance,
try {
std::throw_with_nested(std::runtime_error("error"));
} catch (std::exception &e) {
auto &nested = dynamic_cast<std::nested_exception&>(e);
std::cout << "ok" << std::endl;
}
At the very first time, I thought this code won't be compiled because std::nested_exception is not derived from std::exception and I expected dynamic_cast would do static check of inheritance but I was wrong.
Although I couldn't find related standard specification which explicitly mentions that dynamic_cast allows this, I confirmed that all three major compilers(clang/gcc/msvc) allow dynamic_cast between totally unrelated types.
But still, std::nested_exception is not derived from std::exception, so I thought the dynamic_cast will throw an bad_alloc exception and "ok" never printed. I was wrong again.
Now, I'm wondering how this can work. Is this a something special and exceptional for std::exception and std::nested_exception? Or, can I make another successful dynamic_cast<A&>(b) where type A and type of object b do not have common base class?
That's not sufficient -
std::nested_exceptionis intended to be used as a mixin class, likeIn the above case
dynamic_casthas to check at runtime whether yourstd::exceptionis really aMyExceptionWrapper, in which case it is also astd::nested_exception.This is why it is called dynamic cast, because it has to check the dynamic type at runtime. If you want to perform a static check at compile time, you're looking for static cast.
This is all well documented. We're discussing the following clause from the linked page:
(note that
Base=std::exceptionis polymorphic)Since you can't tell at compile time that a
std::exception&is not really aMyExceptionWrapper, you have to do this at runtime.PS. if you want to avoid accidentally rethrowing inside a
catchblock, just writeinstead. Then you can check for
nullptrto find out whether it succeeded.PPS. As Sean suggests, the
MyExceptionWrapperabove is really more likely to be a type generated bythrow_with_nested, but it has the same effect.