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

стр.

Редакторы IDE

Редакторы исходных текстов в IDE часто показывают типы программных сущностей (например, переменных, параметров, функций и т.п.), когда вы, например, помещаете указатель мыши над ними. Например, пусть у вас есть код

>const int theAnswer = 42;

>auto x = theAnswer;

>auto y = &theAnswer;

Редактор, скорее всего, покажет, что выведенный тип >x представляет собой >int, а выведенный тип >y>const int*.

Чтобы это сработало, ваш код должен быть в более-менее компилируемом состоянии, поскольку такого рода информация поставляется среде разработки компилятором С++ (или как минимум его клиентской частью), работающим в IDE. Если компилятор не в состоянии получить достаточно информации о вашем коде, чтобы выполнить вывод типа, вы не сможете увидеть выведенные типы.

Для простых типов наподобие >int информация из IDE в общем случае вполне точна. Однако, как вы вскоре увидите, когда приходится иметь дело с более сложными типами, информация, выводимая IDE, может оказаться не особенно полезной.

Диагностика компилятора

Эффективный способ заставить компилятор показать выведенный тип — использовать данный тип так, чтобы это привело к проблемам компиляции. Сообщение об ошибке практически обязательно будет содержать тип, который к ней привел.

Предположим, например, что мы хотели бы узнать типы, выведенные для >x и >y из предыдущего примера. Сначала мы объявляем шаблон класса, но не определяем его. Чего- то такого вполне хватит:

>template // Только объявление TD;

>class TD;

Попытки инстанцировать этот шаблон приведут к сообщению об ошибке, поскольку инстанцируемый шаблон отсутствует. Чтобы увидеть типы >x и >y, просто попробуйте инстанцировать TD с их типами:

>TD xType; // Сообщение об ошибке будет

>TD yType; // содержать типы x и y

Я использую имена переменных вида >variableNameType, чтобы проще найти интересующую меня информацию в сообщении об ошибке. Мой компилятор для приведенного выше кода сообщает, в частности, следующее (я выделил интересующую меня информацию о типах):

>error: aggregate 'TD<int> xType' has incomplete type and

>cannot be defined

>error: aggregate 'TD<const int *> yType' has incomplete type

>and cannot be defined

Другой компилятор выдает ту же информацию, но в несколько ином виде:

>error: 'xType' uses undefined class 'TD<int>'

>error: 'yType' uses undefined class 'TD<const int *>'

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

Вывод времени выполнения

Подход с использованием функции вывода для отображения сведений о типе может быть использован только во время выполнения программы, зато он предоставляет полный контроль над форматированием вывода. Вопрос в том, чтобы создать подходящее для вывода текстовое представление информации. “Без проблем, — скажете вы. — Нам на помощь придут >typeid и >std::type_info::name”. В наших поисках информации о выведенных для >x и >y типах можно написать следующий код:

>std::cout << typeid(x).name() << '\n'; // Выведенные типы

>std::cout << typeid(y).name() << '\n'; // для x и y

Этот подход основан на том факте, что вызов >typeid для такого объекта, как >x или >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, вы можете подумать, что задача получения информации о типах решена, но не делайте скоропалительных выводов. Рассмотрим более сложный пример: