Spec-Zone.ru › C++

typeid оператор

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

Используется, когда необходимо знать динамический тип полиморфного объекта, а также для идентификации статического типа.

Синтаксис

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

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

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

Пояснение

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

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

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

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

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

Примечания

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

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

Не гарантируется, что все вычисления выражения typeid для одного и того же типа будут ссылаться на один и тот же объект std::type_info, хотя результаты сравнения будут равны, а 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); // not guaranteed
assert(ti1 == ti2); // guaranteed
assert(ti1.hash_code() == ti2.hash_code()); // guaranteed
assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed

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

typeid

Пример

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

#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 Применяется к Опубликованное поведение Корректное поведение
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
проверка выполняется только на верхнем уровне

См. также

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

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/typeid

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API