Namespaces
Variants

typeid operator

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Interroge les informations d'un type.

Utilisé lorsque le dynamic type d'un polymorphic object doit être connu et pour l'identification de type statique.

Table des matières

Syntaxe

typeid ( type ) (1)
typeid ( expression ) (2)

L'expression typeid est une expression lvalue qui fait référence à un objet ayant une durée de stockage statique , de la version qualifiée const du type polymorphe std::type_info ou d'un type qui en dérive.

Si la définition de la bibliothèque standard de std::type_info n'est pas visible lors de l'utilisation de typeid , le programme est mal formé.

Explication

Si type ou le type de expression est un type classe ou une référence à un type classe, alors ce type classe ne peut pas être un type incomplet .

1) Se réfère à un objet std::type_info représentant le type . Si le type est un type référence, le résultat se réfère à un objet std::type_info représentant la version sans qualificatifs cv du type référencé.
2) Examine expression :
  • Sinon, typeid n' évalue pas l'expression , et l'objet std::type_info qu'il identifie représente le type statique de l'expression. Les conversions lvalue-vers-rvalue, tableau-vers-pointeur ou fonction-vers-pointeur ne sont pas effectuées.
  • La matérialisation temporaire , cependant, est (formellement) effectuée pour les arguments prvalue : l'argument doit être destructible dans le contexte où l'expression typeid apparaît.
(depuis C++17)

Si type ou le type de expression est qualifié cv, le résultat de typeid fait référence à un objet std::type_info représentant le type non qualifié cv (c'est-à-dire, typeid ( const T ) == typeid ( T ) ).

Si typeid est utilisé sur un objet en cours de construction ou de destruction (dans un destructeur ou dans un constructeur, y compris la liste d'initialisation du constructeur ou les initialisateurs par défaut des membres ), alors l'objet std::type_info référencé par ce typeid représente la classe en cours de construction ou de destruction, même s'il ne s'agit pas de la classe la plus dérivée.

  1. Dans d'autres contextes, l'évaluation d'une telle expression entraîne un comportement indéfini.

Notes

Lorsqu'il est appliqué à une expression de type polymorphe, l'évaluation d'une expression typeid peut impliquer un coût d'exécution (une consultation de table virtuelle), sinon l'expression typeid est résolue au moment de la compilation.

Il n'est pas spécifié si le destructeur de l'objet référencé par typeid est exécuté à la fin du programme.

Il n'y a aucune garantie que le même std::type_info objet soit référencé par toutes les évaluations de l'expression typeid sur le même type, bien qu'elles soient comparables comme égales, std::type_info::hash_code de ces type_info objets serait identique, comme le serait leur std::type_index .

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

Mots-clés

typeid

Exemple

L'exemple montrant la sortie utilisant l'une des implémentations où type_info::name retourne les noms complets des types ; filtrer via c++filt -t si vous utilisez gcc ou similaire.

#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';
    }
}

Sortie possible :

======== 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!

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement correct
CWG 492 C++98 lorsque typeid est appliqué à une référence vers un type qualifié cv,
le résultat représentait le type référencé
le résultat représente le
type référencé non qualifié cv
CWG 1416 C++98 la formulation concernant la qualification cv de niveau supérieur
pouvait être mal interprétée
formulation améliorée
CWG 1431 C++98 typeid ne pouvait lever que std::bad_typeid peut lever des
classes dérivées correspondantes
CWG 1954 C++98 il n'était pas clair si le déréférencement de pointeur nul
pouvait être vérifié dans les sous-expressions de expression
vérifié uniquement au niveau supérieur

Voir aussi

contient les informations d'un type, la classe retournée par l'opérateur typeid
(classe)