What Is std::bad_typeid in C++ and When Is It Thrown?
In the C++ programming language, std::bad_typeid is a
standard runtime exception defined in the <typeinfo>
header that signals an invalid use of the typeid operator.
This article explains the definition of std::bad_typeid,
details the exact conditions required for the C++ runtime to throw it,
contrasts its behavior with non-polymorphic types, and provides a clear
code example demonstrating how it is triggered and handled.
What Is std::bad_typeid?
std::bad_typeid is a standard exception class derived
directly from std::exception. It is part of the Run-Time
Type Information (RTTI) mechanism in C++. When dynamic type
identification cannot be safely performed because an object reference
does not actually exist at runtime, the implementation throws this
exception to prevent undefined memory access.
Conditions Under Which std::bad_typeid Is Thrown
The C++ runtime throws std::bad_typeid under a very
specific condition:
- The
typeidoperator is applied to a dereferenced pointer: The expression takes the formtypeid(*ptr). - The pointer is null: The pointer value evaluates to
nullptr(or0). - The type is polymorphic: The static type of the
pointer points to a polymorphic class—meaning the class declares or
inherits at least one
virtualfunction.
Because the class is polymorphic, C++ must determine the actual
dynamic type of the object at runtime by inspecting its virtual method
table (vtable) pointer. When the runtime attempts to inspect
*ptr and discovers that ptr is null, it cannot
read the type metadata. Rather than causing undefined behavior or a
direct segmentation fault, the runtime throws
std::bad_typeid.
Behavior with Non-Polymorphic Types
If the class or type is non-polymorphic (it contains
no virtual functions), typeid is evaluated entirely at
compile time based on the static type of the expression. In that
scenario:
- Writing
typeid(*ptr)on a null pointer to a non-polymorphic type does not evaluate the pointer at runtime. - The runtime check never executes.
std::bad_typeidis never thrown for non-polymorphic types.
Code Example
The following example demonstrates how dereferencing a null pointer
to a polymorphic type triggers std::bad_typeid:
#include <iostream>
#include <typeinfo>
struct PolymorphicBase {
virtual ~PolymorphicBase() = default; // Makes the class polymorphic
};
int main() {
PolymorphicBase* ptr = nullptr;
try {
// Attempting to evaluate dynamic type of a dereferenced null pointer
std::cout << typeid(*ptr).name() << std::endl;
} catch (const std::bad_typeid& e) {
std::cerr << "Caught std::bad_typeid: " << e.what() << std::endl;
}
return 0;
}Prevention and Best Practices
To avoid encountering std::bad_typeid, ensure that any
polymorphic pointer is verified to be non-null before dereferencing it
inside a typeid expression:
if (ptr != nullptr) {
std::cout << typeid(*ptr).name() << '\n';
}When handling generic or dynamically loaded types where null states
cannot be statically ruled out, wrap the typeid evaluation
in a try...catch (const std::bad_typeid&) block.