# typeid operator

From cppreference.com
< cpp‎ | language

Queries information of a type.

Used where the dynamic type of a polymorphic object must be known and for static type identification.

### Syntax

`typeid(` type `)` | (1) |
`typeid(` expression `)` | (2) |

The header <typeinfo> must be included before using `typeid` (if the header is not included, every use of the keyword `typeid` makes the program ill-formed.)

The typeid expression is an lvalue expression which refers to an object with static storage duration, of the polymorphic type const std::type_info or of some type derived from it.

### Explanation

1) Refers to a std::type_info object representing the type type. If type is a reference type, the result refers to a std::type_info object representing the referenced type.
2) Examines the expression expression
a) If expression is a glvalue expression that identifies an object of a polymorphic type (that is, a class that declares or inherits at least one virtual function), the `typeid` expression evaluates the expression and then refers to the std::type_info object that represents the dynamic type of the expression. If the glvalue expression is obtained by applying the unary * operator to a pointer and the pointer is a null pointer value, an exception of type std::bad_typeid or a type derived from std::bad_typeid is thrown.
b) If expression is not a glvalue expression of polymorphic type, `typeid` does not evaluate the expression, and the std::type_info object it identifies represents the static type of the expression. Lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversions are not performed. Temporary materialization, however, is (formally) performed for prvalue arguments: typeid determines the type of the result object. (since C++17)

In all cases, cv-qualifiers are ignored by typeid (that is, typeid(const T) == typeid(T))

If the operand to `typeid` is a class type or a reference to a class type, then that class type must not be an incomplete type.

If `typeid` is used on an object under construction or destruction (in a destructor or in a constructor, including constructor's initializer list or default member initializers), then the std::type_info object referred to by this `typeid` represents the class that is being constructed or destroyed even if it is not the most-derived class.

### Keywords

`typeid`

### Notes

When applied to an expression of polymorphic type, evaluation of a typeid expression may involve runtime overhead (a virtual table lookup), otherwise typeid expression is resolved at compile time.

It is unspecified whether the destructor for the object referred to by `typeid` is executed at the end of the program.

There is no guarantee that the same std::type_info instance will be referred to by all evaluations of the typeid expression on the same type, although std::type_info::hash_code of those type_info objects would be identical, as would be their std::type_index.

    const std::type_info& ti1 = typeid(A);
    const std::type_info& ti2 = typeid(A);

    assert(&ti1 == &ti2); // not guaranteed
    assert(ti1.hash_code() == ti2.hash_code()); // guaranteed
    assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed

### Example

The example showing output using one of the implementations where type_info::name returns full type names; filter through c++filt -t if using gcc or similar.

Run this code

    #include <iostream>
    #include <string>
    #include <typeinfo>

    struct Base {}; // non-polymorphic
    struct Derived : Base {};

    struct Base2 { virtual void foo() {} }; // polymorphic
    struct Derived2 : Base2 {};

    int main() {
        int myint = 50;
        std::string mystr = "string";
        double *mydoubleptr = nullptr;

        std::cout << "myint has type: " << typeid(myint).name() << '\n'
                  << "mystr has type: " << typeid(mystr).name() << '\n'
                  << "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n';

        // std::cout << myint is a glvalue expression of polymorphic type; it is evaluated
        const std::type_info& r1 = typeid(std::cout << myint);
        std::cout << '\n' << "std::cout<<myint has type : " << r1.name() << '\n';

        // std::printf() is not a glvalue expression of polymorphic type; NOT evaluated
        const std::type_info& r2 = typeid(std::printf("%d\n", myint));
        std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n';

        // Non-polymorphic lvalue is a static type
        Derived d1;
        Base& b1 = d1;
        std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n';

        Derived2 d2;
        Base2& b2 = d2;
        std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n';

        try {
            // dereferencing a null pointer: okay for a non-polymorphic expression
            std::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n';
            // dereferencing a null pointer: not okay for a polymorphic lvalue
            Derived2* bad_ptr = nullptr;
            std::cout << "bad_ptr points to... ";
            std::cout << typeid(*bad_ptr).name() << '\n';
        } catch (const std::bad_typeid& e) {
             std::cout << " caught " << e.what() << '\n';
        }
    }

Possible output:

    myint has type: int
    mystr has type: std::basic_string<char, std::char_traits<char>, std::allocator<char> >
    mydoubleptr has type: double*
    50
    std::cout<<myint has type : std::basic_ostream<char, std::char_traits<char> >
    printf("%d\n",myint) has type : int
    reference to non-polymorphic base: Base
    reference to polymorphic base: Derived2
    mydoubleptr points to double
    bad_ptr points to...  caught std::bad_typeid

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/typeid&oldid=108605"