Как правильно определить тип переменной в C ++. Я попытался это, чтобы определить тип переменной:
int a = 5;
std::cout << typeid(a).name() << std::endl;
И вместо ожидаемого вывода int, он дает вам:
i
Я очень запутался в том, почему это происходит. Это почему-то дает вам только первую букву того типа, который вы объявляете переменной. Int не единственный … также это:
char a = 'A'
std::cout << typeid(a).name() << std::endl;
Есть ли простой способ обойти это? Любая помощь будет оценена!
Есть две проблемы с вашим кодом,
во-первых typeid(..).name()
возвращает строку, определенную реализацией, это может быть любая допустимая строка, она может вернуть ""
для каждого типа он может даже возвращать разные значения для каждого выполнения программы (хотя я считаю, что значение не может измениться во время выполнения). GCC (и Clang?) Возвращают нечитаемые имена, тогда как Visual C ++ возвращает разумные (в этом случае int
)
Во-вторых, если тип a
это полиморфный тип, typeid(a)
вернет typeid
соответствующий динамическому типу a
а не тот тип, который был использован для объявления a
вместо typeid(decltype(a))
,
К сожалению, не существует стандартного способа получения имени типа таким образом, чтобы он был читабельным или правильным синтаксисом C ++.
(увидеть Отмена результата std :: type_info :: name если вы хотите способ, который работает в GCC)
РЕДАКТИРОВАТЬ Используя Boost, вы можете попробовать std::cout << boost::typeindex::type_id<decltype(a)>().pretty_name() << std::endl;
, увидеть Получение удобочитаемых и искаженных имен типов
Я имею в виду, даже если это не понятно. Например, если int равно 32432423423403095590353095309530953, то всегда будет одинаковым. Так что я могу легко установить функцию, которая будет возвращать тип переменной …
Результаты, которые вы получаете, уже выполняют это. Возможно, это поможет объяснить, как именно используемая реализация C ++ получает строки, которые вы видите.
G ++ реализует typeid(...).name()
такой, что он возвращает искаженное имя типа ABI. Это особый способ представления типов, который используется в скомпилированных объектных файлах и библиотеках. Если вы скомпилируете код C ++ в сборку, вы увидите «символы», которые определяют, к какой функции или данным относится полученный код сборки. Например, возьмите функцию:
int foo(double a, char b) {
return a + b;
}
скомпилировать его в сборку, и вы увидите что-то вроде следующего:
_Z3foodc:
.LFB0:
.cfi_startproc
movsbl %dil, %edi
cvtsi2sd %edi, %xmm1
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
ret
.cfi_endproc
Первая строка здесь — это «искаженный» символ, который используется для идентификации функции int foo(double,char)
, Он содержит «Z3foo», который представляет имя функции, а затем «d», который представляет тип первого аргумента, и «c», который представляет тип второго аргумента. Этот символ используется для идентификации функции в двоичном объектном файле, в индексах библиотеки, другими скомпилированными объектами, которые хотят связать эту функцию и т. Д.
Вы также можете раскладывать символы используя инструмент C ++ Filter. Этот инструмент просматривает любой передаваемый вами текст в поисках вещей, соответствующих синтаксису искажения, и преобразует их во что-то более похожее на то, как эти типы названы в исходном коде C ++.
G ++ реализует Itanium C ++ ABI схема искажения. Он используется большинством компиляторов платформы Unix.
Итак, вернемся к вашему коду, угадайте, как тип ‘int’ представлен в этих символах.
Itanium ABI определяет дополнительная функция для разборки. Вот пример, использующий это.
Имена типов не должны быть такими, как вы ожидаете. Увидеть этот ответ для способа получить фактическое имя типа. Обратите внимание — он работает только на gcc и, с некоторыми дополнительная установка, на лязг.
В Visual C ++ вы должны вызывать UnDecorateSymbolName, но, по-видимому, называются целые int
там