Use the typeid Operator in C++

This article explains and demonstrates how to utilize the typeid operator in C++.

Use the typeid Operator to Retrieve the Type Name of the Object in C++

You can use the typeid operator to retrieve the type information of the given expression or object. It returns a reference to the std::type_info standard-library type, which is defined in a <typeinfo> header.

The std::type_info object has the member function name that you can utilize to return a character string describing the underlying type of the argument object. Note that the type information retrieved by typeid is implementation-dependent. Namely, the most common compilers gcc and clang return mangled names, as demonstrated in the next code example.

Other implementations like Microsoft Visual C++ display information in more readable forms. Stil, keep in mind that you can still learn to identify the names for the built-in types displayed by the former implementation. For example, the int object returns an i character, and a pointer to the int object returns a Pi character string.

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

using std::cout; using std::endl;
using std::string; using std::cin;

int main() {
    int i1 = 1234;
    string str1("arbitrary string");
    auto ptr = &i1;

    cout << "i1 type: " << typeid(i1).name() << '\n'
         << "str1 type: " << typeid(str1).name() << '\n'
         << "ptr type: " << typeid(ptr).name() << endl;

    const std::type_info& r1 = typeid(i1);
    cout << '\n' << "i1 type: " << r1.name() << '\n';

    return EXIT_SUCCESS;
}

Output:

i1 type: i
str1 type: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
ptr type: Pi

i1 type: i

On the other hand, if we call the typeid command on references to objects, we will find that the retrieved type information is not always accurate and sometimes too cryptic to be readable. The following example shows such a case where the second call to the typeid operator returns the type information incorrectly.

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

using std::cout; using std::endl;

struct Base {};
struct Derived : Base {};

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

int main() {
    Derived d1;
    Base& b1 = d1;
    cout << "non-polymorphic base: " << typeid(b1).name() << '\n';

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

    return EXIT_SUCCESS;
}

Output:

non-polymorphic base: 4Base
polymorphic base: 8Derived2

This behavior can be corrected using the Boost TypeIndex library function, type_id_with_cvr, which can return the type information accurately. Generally, objects with the const, volatile, & and && modifiers all cause the incorrect type information when typeid operator is used; therefore, you should better rely on the type_id_with_cvr function.

The following code example requires the Boost library to be installed on the system, and the type_id_with_cvr function is under the boost::typeindex namespace.

#include <iostream>
#include <string>
#include <typeinfo>
#include <boost/type_index.hpp>

using std::cout; using std::endl;
using boost::typeindex::type_id_with_cvr;

struct Base {};
struct Derived : Base {};

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

int main() {
    Derived d1;
    Base& b1 = d1;

    Derived2 d2;
    Base2& b2 = d2;

    cout << type_id_with_cvr<decltype(b1)>().pretty_name() << '\n';
    cout << type_id_with_cvr<decltype(b2)>().pretty_name() << '\n';

    return EXIT_SUCCESS;
}

Output:

Base&
Base2&
Contribute
DelftStack is a collective effort contributed by software geeks like you. If you like the article and would like to contribute to DelftStack by writing paid articles, you can check the write for us page.

Related Article - C++ Operator

  • Operators in C++
  • Overload Subscript Operator in C++