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

Запрашивает информацию о типе.

Используется там, где dynamic type polymorphic object должен быть известен, а также для статической идентификации типа.

Содержание

Синтаксис

typeid ( тип ) (1)
typeid ( выражение ) (2)

Выражение typeid является lvalue-выражением , которое ссылается на объект с статической продолжительностью хранения , имеющий const-квалифицированную версию полиморфного типа std::type_info или некоторого типа, производного от него.

Если определение стандартной библиотеки для std::type_info не видимо при использовании typeid , программа является некорректной.

Объяснение

Если type или тип expression является классом или ссылкой на класс, то этот класс не может быть неполным типом .

1) Обозначает объект std::type_info , представляющий тип type . Если type является ссылочным типом, результат обозначает объект std::type_info , представляющий версию базового типа без cv-квалификаторов.
2) Анализирует expression :
  • В противном случае typeid не вычисляет выражение , и объект std::type_info , который он идентифицирует, представляет статический тип выражения. Преобразования lvalue-to-rvalue, array-to-pointer или function-to-pointer не выполняются.
(since C++17)

Если type или тип expression является cv-квалифицированным, результат typeid ссылается на объект std::type_info представляющий тип без cv-квалификаторов (то есть, typeid ( const T ) == typeid ( T ) ).

Если typeid используется для объекта в процессе конструирования или разрушения (в деструкторе или конструкторе, включая список инициализации конструктора или инициализаторы членов по умолчанию ), то объект std::type_info , на который ссылается этот typeid , представляет класс, который конструируется или разрушается, даже если это не самый производный класс.

  1. В других контекстах вычисление такого выражения приводит к неопределённому поведению.

Примечания

При применении к выражению полиморфного типа, вычисление выражения typeid может требовать дополнительных затрат времени выполнения (поиск в виртуальной таблице), в противном случае выражение typeid разрешается во время компиляции.

Не определено, вызывается ли деструктор для объекта, на который ссылается typeid в конце выполнения программы.

Нет гарантии, что один и тот же объект std::type_info будет использоваться всеми вычислениями выражения typeid для одного типа, хотя они будут сравниваться как равные. std::type_info::hash_code этих объектов type_info будет идентичным, как и их std::type_index .

const std::type_info& ti1 = typeid(A);
const std::type_info& ti2 = typeid(A);
assert(&ti1 == &ti2); // не гарантируется
assert(ti1 == ti2); // гарантируется
assert(ti1.hash_code() == ti2.hash_code()); // гарантируется
assert(std::type_index(ti1) == std::type_index(ti2)); // гарантируется

Ключевые слова

typeid

Пример

Пример, показывающий вывод с использованием одной из реализаций, где type_info::name возвращает полные имена типов; отфильтруйте через c++filt -t при использовании gcc или аналогичного.

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

Возможный вывод:

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

Отчёты о дефектах

Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
CWG 492 C++98 когда typeid применяется к ссылке на cv-квалифицированный
тип, результат представлял ссылочный тип
результат представляет
cv-неквалифицированный ссылочный тип
CWG 1416 C++98 формулировка относительно квалификации верхнего уровня
cv могла быть неверно истолкована
улучшена формулировка
CWG 1431 C++98 typeid мог выбрасывать только std::bad_typeid разрешено выбрасывать
сопоставимые производные классы
CWG 1954 C++98 было неясно, может ли разыменование нулевого указателя
проверяться в подвыражениях expression
проверяется только на верхнем уровне

Смотрите также

содержит информацию о типе, класс, возвращаемый оператором typeid
(класс)