Espacios de nombres
Variantes
Acciones

Operador typeid

De cppreference.com
< cpp‎ | language
 
 
 
 

Consulta información de un tipo.

Usado donde el tipo dinámico de un objeto polimórfico debe conocerse y para identificación de tipos estáticos.

Contenido

[editar] Sintaxis

typeid( tipo ) (1)
typeid( expresión ) (2)

El archivo de encabezado <typeinfo> se debe incluir antes de usar typeid (si no se incluye el archivo de encabezado, cada uso de la palabra reservada typeid hace que el programa este mal formado).

La expresión typeid es una expresión lvalue que se refiere a un objeto con duración de almacenamiento estática, de tipo polimórfico const std::type_info o alguno derivado del mismo.

[editar] Explicación

1) Se refiere a un objeto std::type_info que representa el tipo tipo. Si tipo es un tipo referencia, el resultado se refiere a un objeto std::type_info que representa el tipo al que hace referencia.
2) Examina la expresión expresión
a) Si la expresión es una expresión glvalue que identifica un objeto de tipo polimórfico (es decir, una clase que declara o hereda al menos una función virtual), la expresión typeid evalúa la expresión y luego refiere al objeto std::type_info que representa el tipo dinámico de la expresión. Si la expresión glvalue se obtiene aplicando el operado unario * al puntero y el puntero tiene un valor puntero nulo, se lanza una excepción de tipo std::bad_typeid o un tipo derivado de std::bad_typeid .
b) Si la expresión no es una expresión glvalue de tipo polimórfico, typeid no evalúa la expresión, y el objeto std::type_info identifica el tipo estático de la expresión. No se realiza coneversiones de lvalue a rvalue, matriz a puntero, o función a puntero. La materialización temporal, sin embargo, se realiza para argumentos prvalue: typeid determina el tipo del objeto resultado. (desde C++17)

En todos los casos, los calificadores constante/volátil se ignoran por parte de typeid (es decir, typeid(T) == typeid(const T))

Si el operando de typeid es un tipo clase o referencia a tipo clase, entonces este tipo clase no debe ser un tipo incompleto.

Si se usa typeid en un objeto en construcción o destrucción (en un destructor o constructor, incluyendo lista incializadora del constructor o incializadores de miembro por defecto), entonces el objeto std::type_info al que hace referencia este typeid representa la clase que se está construyendo o destruyendo incluso si no es la clase más derivada.

[editar] Palabra reservada

typeid

[editar] Notas

Cuando se aplica a una expresión de tipo polimórfico, la evaluación de la expresión typeid puede implicar mayor tiempo de ejecución (búsqueda en una tabla virtual), en otro caso la expresión typeid se resuelve en tiempo de compilación.

No se especifica si el destructor para el objeto al que hace referencia typeid se ejecuta al final del programa.

No se garantiza que la misma instancia de std::type_info será referida por todas las evaluaciones de la expresión typeid sobre el mismo tipo, aunque std::type_info::hash_code de esos objetos type_info serían idénticos, como también su std::type_index.

const std::type_info& ti1 = typeid(A);
const std::type_info& ti2 = typeid(A);
 
assert(&ti1 == &ti2); // no garantizado
assert(ti1.hash_code() == ti2.hash_code()); // garantizado
assert(std::type_index(ti1) == std::type_index(ti2)); // garantizado


[editar] Ejemplo

El ejemplo muestra la salida utilizando implementaciones donde type_info::name devuelve los nombres completos del tipo; filre a través de c++filt -t si usa gcc o similar.

#include <iostream>
#include <string>
#include <typeinfo>
 
struct Base {}; // no polimórfico
struct Derived : Base {};
 
struct Base2 { virtual void foo() {} }; // polimórfico
struct Derived2 : Base2 {};
 
int main() {
    int myint = 50;
    std::string mystr = "string";
    double *mydoubleptr = nullptr;
 
    std::cout << "myint tiene tipo: " << typeid(myint).name() << '\n'
              << "mystr tiene tipo: " << typeid(mystr).name() << '\n'
              << "mydoubleptr tiene tipo: " << typeid(mydoubleptr).name() << '\n';
 
    // “std::cout << myint” es una expresión glvalue de tipo polimórfico; se evalúa
    const std::type_info& r1 = typeid(std::cout << myint);
    std::cout << '\n' << "std::cout<<myint tiene tipo: " << r1.name() << '\n';
 
    // std::printf() no es una expresión glvalue de tipo polimórfico; no se evalúa
    const std::type_info& r2 = typeid(std::printf("%d\n", myint));
    std::cout << "printf(\"%d\\n\",myint) tiene tipo: " << r2.name() << '\n';
 
    // Un lvalue no polimórfico es un tipo estático
    Derived d1;
    Base& b1 = d1;
    std::cout << "referencia a base no polimórfica: " << typeid(b1).name() << '\n';
 
    Derived2 d2;
    Base2& b2 = d2;
    std::cout << "referencia a base polimórfica: " << typeid(b2).name() << '\n';
 
    try {
        // desreferenciación de un puntero nulo: correcto para una expresión no polimórfica
        std::cout << "mydoubleptr apunta a " << typeid(*mydoubleptr).name() << '\n'; 
        // desreferenciación de un puntero nulo: no correcto para un lvalue polimórfico
        Derived2* bad_ptr = nullptr;
        std::cout << "bad_ptr apunta a... ";
        std::cout << typeid(*bad_ptr).name() << '\n';
    } catch (const std::bad_typeid& e) {
         std::cout << " caught " << e.what() << '\n';
    }
}

Posible salida:

myint tiene tipo: int
mystr tiene tipo: std::basic_string<char, std::char_traits<char>, std::allocator<char> >
mydoubleptr tiene tipo: double*
 
“std::cout<<myint” tiene tipo : std::basic_ostream<char, std::char_traits<char> >
printf("%d\n",myint) tiene tipo : int
referencia a base no polimórfica: Base
referencia a base polimórfica: Derived2
mydoubleptr apunta a double
bad_ptr apunta a...  caught std::bad_typeid