Spec-Zone.ru › C++

Оператор typeid

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

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

Синтаксис

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

Заголовочный файл <typeinfo> должен быть включён или импортирован(с C++20) или стандартный модуль библиотеки импортирован(с C++23) перед использованием typeid, в противном случае программа некорректна.

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

Описание

Если тип тип или выражение — это тип класса или ссылка на тип класса, то этот тип класса не может быть неполным типом.

1) Ссылается на объект std::type_info , представляющий тип тип. Если тип — тип ссылки, результат ссылается на объект std::type_info , представляющий неквалифицированную версию типа ссылки.
2) Исследует выражение выражение
a) Если выражение — выражение-ссылка(до C++11)выражение с глобальной ссылкой(с C++11) , которое идентифицирует объект полиморфного типа (то есть класс, который объявляет или наследует как минимум одну виртуальную функцию), выражение typeid вычисляет выражение и затем ссылается на объект std::type_info , который представляет динамический тип выражения. Если выражение получено при применении унарного оператора * к указателю, а указатель имеет нулевое значение, выбрасывается исключение типа std::bad_typeid(до C++14)соответствующего обработчику типа std::bad_typeid(с C++14).
b) Если выражение не является выражением-ссылкой(до C++11)выражением с глобальной ссылкой(с C++11) полиморфного типа, typeid не вычисляет выражение, и объект std::type_info , который он идентифицирует, представляет статический тип выражения. Преобразования "ссылка в значение", "массив в указатель" или "функция в указатель" не выполняются. Однако временное создание происходит (формально) для аргументов типа правое значение: аргумент должен быть удаляемым в контексте, в котором появляется выражение typeid. (с C++17)

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

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

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

typeid

Примечания

При применении к выражению полиморфного типа вычисление выражения 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); // not guaranteed
assert(ti1 == ti2); // guaranteed
assert(ti1.hash_code() == ti2.hash_code()); // guaranteed
assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed

Пример

В примере показан вывод с использованием одной из реализаций, где 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 Применён к Поведение, как опубликовано Корректное поведение
CWG 492 C++98 при применении typeid к ссылке на тип с квалификатором cv,
результат представляет сославшийся тип
результат представляет неквалифицированный сославшийся тип
CWG 1416 C++98 формулировка, касающаяся квалификации cv верхнего уровня, может быть неправильно истолкована улучшена формулировка

См. также

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

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

Spec-Zone.ru

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