Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 32



или >y, дает объект >std: :type_info, а он имеет функцию-член >name, которая дает С-строку (т.е. >const char*), представляющую имя типа.

Не гарантируется, что вызов >std::type_info::name вернет что-то разумное, но его реализации изо всех сил пытаются быть полезными. Уровень этой полезности варьируется от компилятора к компилятору. Компиляторы GNU и Clang, например, сообщают, что тип >x — это “>i” а тип >y — “>PKi”. Эти результаты имеют смысл, если вы будете знать, что “>i” у данных компиляторов означает “>int”, а “>PK” — “указатель на константу”.

(Оба компилятора поддерживают инструмент >c++filt, который расшифровывает эти имена.) Компилятор Microsoft генерирует менее зашифрованный вывод: “>int” для >x и “i>nt const *”для >y.

Поскольку это корректные результаты для типов >x и >y, вы можете подумать, что задача получения информации о типах решена, но не делайте скоропалительных выводов. Рассмотрим более сложный пример:

>template             // Шаблонная функция,

>void f(const T& param);          // вызываемая далее


>std::vector createVec(); // Фабричная функция


>const auto vw = createVec();     // Инициализация vw возвратом

>                                 // фабричной функции


>if (!vw.empty()) {

> f(&vw[0]);                      // Вызов f

>}

Этот код, включающий пользовательский тип (>Widget), контейнер STL (>std::vector) и переменную auto (>vw), является более представительным и интересным примером. Было бы неплохо узнать, какие типы выводятся для параметра типа шаблона и для параметра param функции >f.

Воспользоваться >typeid в этой задаче достаточно просто. Надо всего лишь добавить немного кода в функцию f для вывода интересующих нас типов:

>template

>void f(const T& param) {

> using std::cout;


> // Вывод в поток cout типа T:

> cout << "Т = " << typeid(T).name() << '\n';


> // Вывод в поток cout типа param:

> cout << "param = " << typeid(param).name() << '\n';

>}

Выполнимые файлы, полученные с помощью компиляторов GNU и Clang, дают следующий результат:

>Т     = PK6Widget

>param = PK6Widget

Мы уже знаем, что в этих компиляторах >PK означает указатель на константу, так что вся загадка — в цифре >6. Это просто количество символов в следующем за ней имени класса (>Widget). Таким образом, данные компиляторы сообщают нам, что и , и >param имеют один и тот же тип — >const Widget*. Компилятор Microsoft согласен:

>Т     = class Widget const *

>param = class Widget const *

Три независимых компилятора дают одну и ту же информацию, что свидетельствует о том, что эта информация является точной. Но давайте посмотрим более внимательно. В шаблоне