> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C++ Typeid

The `typeid` operator is a C++ language facility that queries type information at compile-time or runtime. It yields an lvalue of static type `const std::type_info` representing the exact type of the operand.

## Syntax

```cpp theme={"dark"}
typeid(type-id)
typeid(expression)
```

To use the `typeid` operator, the `<typeinfo>` standard library header must be included.

## Completeness Requirement

When `typeid` is applied to a *type-id* representing a class type, or to an *expression* whose static type is a class type, that class type must be completely defined. Applying `typeid` to an incomplete type results in a compilation error.

## Evaluation Mechanics

The evaluation strategy of `typeid` strictly depends on the value category and polymorphism of its operand:

**1. Runtime Evaluation (Dynamic Type / RTTI)**
Runtime evaluation *only* occurs if the operand is a **glvalue** expression of a polymorphic class type (a class declaring or inheriting at least one virtual function). The operator inspects the virtual table (vtable) of the object to determine its most derived dynamic type. Because it requires runtime resolution, the expression itself is evaluated.

**2. Compile-Time Evaluation (Static Type)**
For all other operands, `typeid` is resolved entirely at compile-time based on the static type. This includes:

* Any *type-id*.
* Expressions of non-polymorphic types.
* **prvalue** expressions of polymorphic types (e.g., `typeid(Base())`).

In these compile-time scenarios, the expression is treated as an *unevaluated operand*; no runtime execution of the expression occurs.

## Type Adjustments

Before the `std::type_info` object is generated, the C++ compiler applies specific type adjustments:

* **Reference Stripping:** If the operand is a *type-id* representing a reference type (`T&` or `T&&`), `typeid` evaluates the referenced type (`T`). For *expression* operands, this rule is implicitly satisfied because C++ expressions do not possess reference types; references are dropped during standard expression evaluation before `typeid` is applied.
* **CV-Qualifier Stripping:** Top-level `const` and `volatile` qualifiers are ignored. `typeid(const T)` and `typeid(T)` yield `std::type_info` objects that represent the same type and compare equal via `operator==`. Pointers to const types (`const T*`), however, retain their constness because the qualifier is not top-level.

## Exception Handling

When evaluating a polymorphic glvalue expression at runtime, if the operand is a dereferenced null pointer (e.g., `*ptr` where `ptr` evaluates to a null pointer value), the `typeid` operator throws an exception of type `std::bad_typeid`. Dereferencing a null pointer in a compile-time evaluated context (such as a non-polymorphic type or a prvalue) does not throw, because the expression is an unevaluated operand.

## Syntax Visualization

```cpp theme={"dark"}
#include <typeinfo>
#include <cassert>

struct Base { virtual ~Base() = default; }; // Polymorphic, completely defined
struct Derived : Base {};
struct NonPolyBase {};                      // Non-polymorphic, completely defined

struct Incomplete; // Incomplete type

Base make_base(); // Function returning a prvalue

int main() {
    // ERROR: typeid(Incomplete) would fail to compile because the type is incomplete.

    // 1. Compile-time evaluation: prvalue of a polymorphic type
    // make_base() is an unevaluated operand. No function call occurs at runtime.
    const std::type_info& t1 = typeid(make_base()); 

    // 2. Runtime evaluation: glvalue of a polymorphic type
    Derived d;
    Base& b_ref = d;
    // Evaluates at runtime to the dynamic type (Derived) via the vtable
    const std::type_info& t2 = typeid(b_ref); 

    // 3. Compile-time evaluation: glvalue of a non-polymorphic type
    NonPolyBase npb;
    NonPolyBase& npb_ref = npb;
    // Evaluates at compile-time to the static type (NonPolyBase)
    const std::type_info& t3 = typeid(npb_ref); 

    // 4. Type-ids, reference stripping, and CV-qualifier stripping
    assert(typeid(const int) == typeid(int));
    assert(typeid(int&) == typeid(int)); 

    // 5. Exception on null polymorphic glvalue dereference
    Base* null_ptr = nullptr;
    try {
        const std::type_info& t4 = typeid(*null_ptr); // Throws std::bad_typeid
    } catch (const std::bad_typeid& e) {
        // Exception caught
    }

    // 6. Unevaluated operand (Non-polymorphic null pointer)
    NonPolyBase* np_null = nullptr;
    const std::type_info& t5 = typeid(*np_null); 
    // Safe: Evaluates to NonPolyBase at compile-time. No exception thrown.

    return 0;
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C++ Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
