Оператор typeid
Запрашивает информацию о типе.
Используется, когда необходимо узнать динамический тип полиморфного объекта и для статической идентификации типа.
Синтаксис
typeid ( тип ) | (1) | |
typeid ( выражение ) | (2) |
Заголовочный файл <typeinfo> должен быть включён или импортирован(с C++20) или стандартный модуль библиотеки импортирован(с C++23) перед использованием typeid, в противном случае программа некорректна.
Выражение typeid является выражением-ссылкой, которое ссылается на объект со статическим сроком жизни, квалифицированной константой версии полиморфного типа std::type_info или некоторого типа, производного от него.
Описание
Если тип тип или выражение — это тип класса или ссылка на тип класса, то этот тип класса не может быть неполным типом.
std::type_info , представляющий тип тип. Если тип — тип ссылки, результат ссылается на объект std::type_info , представляющий неквалифицированную версию типа ссылки.typeid вычисляет выражение и затем ссылается на объект std::type_info , который представляет динамический тип выражения. Если выражение получено при применении унарного оператора * к указателю, а указатель имеет нулевое значение, выбрасывается исключение типа std::bad_typeid(до C++14)соответствующего обработчику типа std::bad_typeid(с C++14).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 , выполнен в конце программы.
Нет гарантии, что один и тот же экземпляр 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 верхнего уровня, может быть неправильно истолкована | улучшена формулировка |
См. также
| содержит информацию о некоторых типах, сгенерированную реализацией. Это класс, возвращаемый оператором typeid. (класс) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/typeid