typeid
operator
Consulta información de un tipo.
Se utiliza cuando el dynamic type de un polymorphic object debe ser conocido y para identificación de tipo estático.
Contenidos |
Sintaxis
typeid (
type
)
|
(1) | ||||||||
typeid (
expression
)
|
(2) | ||||||||
La expresión typeid es una expresión lvalue que se refiere a un objeto con almacenamiento estático , del tipo polimórfico calificado como const std::type_info o algún tipo derivado del mismo.
Si la definición de la biblioteca estándar de std::type_info no es visible al usar typeid , el programa está mal formado.
Explicación
Si type o el tipo de expression es un tipo clase o una referencia a un tipo clase, entonces ese tipo clase no puede ser un incomplete type .
- Si la expresión es un lvalue (until C++11) un glvalue (since C++11) 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 se refiere al objeto std::type_info que representa el tipo dinámico de la expresión.
-
- Si la expresión es una expresión de indirección y su operando se evalúa como un valor de puntero nulo , se lanza una excepción del tipo que coincide con los manejadores de tipo std::bad_typeid [1] .
- De lo contrario, typeid no evalúa la expresión , y el objeto std::type_info que identifica representa el tipo estático de la expresión. No se realizan conversiones de lvalue-a-rvalue, array-a-puntero o función-a-puntero.
|
(since C++17) |
Si type o el tipo de expression está calificado con cv, el resultado de typeid se refiere a un objeto std::type_info que representa el tipo sin calificación cv (es decir, typeid ( const T ) == typeid ( T ) ).
Si typeid se utiliza en un objeto en construcción o destrucción (en un destructor o en un constructor, incluyendo la lista de inicializadores del constructor o los inicializadores predeterminados de miembros ), entonces el objeto std::type_info al que se refiere este typeid representa la clase que se está construyendo o destruyendo, incluso si no es la clase más derivada.
- ↑ En otros contextos, evaluar dicha expresión resulta en comportamiento indefinido.
Notas
Cuando se aplica a una expresión de tipo polimórfico, la evaluación de una expresión typeid puede implicar sobrecarga en tiempo de ejecución (una búsqueda en la tabla virtual), de lo contrario la expresión typeid se resuelve en tiempo de compilación.
No está especificado si el destructor para el objeto referido por typeid se ejecuta al final del programa.
No hay garantía de que el mismo
std::type_info
objeto sea referido por todas las evaluaciones de la expresión typeid en el mismo tipo, aunque compararían iguales, el
std::type_info::hash_code
de esos objetos
type_info
sería idéntico, al igual que 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 == ti2); // garantizado assert(ti1.hash_code() == ti2.hash_code()); // garantizado assert(std::type_index(ti1) == std::type_index(ti2)); // garantizado
Palabras clave
Ejemplo
El ejemplo muestra la salida usando una de las implementaciones donde type_info::name devuelve nombres de tipo completos; filtrar a través de c++filt -t si se usa gcc o similar.
#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); // side-effect: prints 50 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'; { {
Salida posible:
======== output from Clang ========
myint has type: i
mystr has type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
mydoubleptr has type: Pd
50
std::cout<<myint has type : NSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
printf("%d\n",myint) has type : i
reference to non-polymorphic base: 4Base
reference to polymorphic base: 8Derived2
mydoubleptr points to d
bad_ptr points to... caught std::bad_typeid
======== output from MSVC ========
myint has type: int
mystr has type: class std::basic_string<char,struct std::char_traits<char>,⮠
class std::allocator<char> >
mydoubleptr has type: double * __ptr64
50
std::cout<<myint has type : class std::basic_ostream<char,struct std::char_traits<char> >
printf("%d\n",myint) has type : int
reference to non-polymorphic base: struct Base
reference to polymorphic base: struct Derived2
mydoubleptr points to double
bad_ptr points to... caught Attempted a typeid of nullptr pointer!
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 492 | C++98 |
cuando
typeid
se aplica a una referencia a tipo cv-calificado,
el resultado representaba el tipo referenciado |
el resultado representa el
tipo referenciado sin calificación cv |
| CWG 1416 | C++98 |
la redacción sobre calificación cv de nivel superior
podría ser malinterpretada |
se mejoró la redacción |
| CWG 1431 | C++98 | typeid solo podía lanzar std::bad_typeid |
se permite lanzar
clases derivadas comparables |
| CWG 1954 | C++98 |
no estaba claro si la desreferencia de puntero nulo
puede verificarse en subexpresiones de expresión |
solo se verifica a nivel superior |
Véase también
|
contiene información de algún tipo, la clase devuelta por el operador typeid
(clase) |