Имена, возвращаемые функцией typeid, очень сокращены, зависят от компилятора и не предназначены для использования человеком. Вы можете «разобрать» их (это настоящий термин!), Либо в коде с помощью чего-то вроде gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , с помощью таких утилит командной строки, как c++filt, либо с помощью любого из различных онлайн-деманглеров например, demangler.com .
cincodenada
33
Для статических утверждений введен C ++ 11, decltypeкоторый весьма полезен в определенных сценариях.
Основное различие между C ++ и Javascript заключается в том, что C ++ - это язык со статической типизацией, а javascript - динамический.
В языках с динамической типизацией переменная может содержать что угодно, и ее тип задается значением, которое она содержит, момент за моментом. В языках со статической типизацией тип переменной объявлен и не может быть изменен.
Может быть динамическая диспетчеризация и составление объектов и подтипирование (наследование и виртуальные функции), а также статическая диспетчеризация и супертипирование (через шаблон CRTP), но в любом случае тип переменной должен быть известен компилятору.
Если вы в состоянии не знать, что это такое или может быть, то это потому, что вы что-то спроектировали, поскольку язык имеет динамическую систему типов.
Если это так, вам лучше переосмыслить свой дизайн, поскольку он идет в землю, не естественную для используемого вами языка (больше всего похоже на движение по автостраде с гусеницей или по воде на машине).
Если в C ++ есть динамическое изменение, я думаю, это было бы здорово, и функции typeof и parseInt, parseFloat также пригодятся, но я не знаю, почему разработчики C ++ делают это слишком сложно, например! кто говорит, что хорошо писать cout << "String"
Вакас Тахир
решительность самая лучшая !!!! #include <поток> строка str ("1912"); int strtointval; stringstream (str) >> strtointval;
Вакас Тахир,
@Waqas Что? Люди, которые говорят, что это лучше всего, - это люди, которые определяют язык, и, IMO, они в значительной степени имеют последнее слово во всем, что с ним связано - например, о хороших методах кодирования. Не могли бы вы перефразировать этот комментарий, чтобы он имел больше смысла?
Иск Фонда Моники
Я полностью не согласен. Java, C #, PHP, Perl, Python и другие были разработаны на C и C ++ и не являются гусеницами. (Когда вы создаете приложение базы данных для открытия таблиц переменных из «неизвестных» баз данных, вам нужно управлять типом поля в соответствии со схемой переменных и наоборот «очень» динамичным способом;))
TomeeNS
@TomeeNS: Нет. Они написаны на C и C ++, а не разработаны . Они созданы для того, чтобы делать свою работу. У них есть динамический тип, даже если сами C и C ++ этого не делают. В этом нет ничего странного.
Эмилио Гаравалья
8
Обычно поиск типа переменной в C ++ - неправильный вопрос. Обычно это что-то, что вы носите с собой из процедурных языков, таких как, например, C или Pascal.
Если вы хотите закодировать разное поведение в зависимости от типа, попробуйте узнать, например, о перегрузке функций и наследовании объектов . Это не будет иметь смысла сразу после вашего первого дня изучения C ++, но продолжайте.
Не совсем, допустим, у вас есть класс Object и подкласс Book. Теперь представьте, что у вас есть Коробка, в которой может храниться множество объектов, но по какой-то причине вы хотите перечислить все книги внутри нее. Проверка типа намного чище, чем необходимость добавить метод «type» в Object, а затем переопределить его в Book, чтобы вернуть что-то вроде «book»
Пауло Сезар
Как и в любом правиле, есть исключения (отсюда и мое «обычно»!), А контейнеры, как правило, усложняют теорию типов. Я никогда не слишком увлекался контейнерами-полиморфными-объектами… в большинстве случаев достаточно шаблонных универсальных типов контейнеров, которые намного чище.
Pontus Gagge
Вы не пользуетесь шаблонами?
Брайан Грейс
6
Я считаю, что у меня есть допустимый вариант использования typeid (), так же как и sizeof (). Для функции шаблона мне нужен специальный код, основанный на переменной шаблона, чтобы я предлагал максимальную функциональность и гибкость.
Создание одного экземпляра функции для каждого поддерживаемого типа намного компактнее и удобнее, чем использование полиморфизма. Даже в этом случае я мог бы использовать этот трюк, чтобы написать тело функции только один раз:
Обратите внимание: поскольку в коде используются шаблоны, приведенный ниже оператор switch должен статически разрешаться только в один блок кода, оптимизируя все ложные случаи, AFAIK.
Рассмотрим этот пример, где нам может потребоваться обработать преобразование, если T относится к одному типу по сравнению с другим. Я использую его для специализации классов для доступа к оборудованию, где оборудование будет использовать тип myClassA или myClassB. При несовпадении мне нужно потратить время на преобразование данных.
switch((typeid(T)){casetypeid(myClassA):// handle that casebreak;casetypeid(myClassB):// handle that casebreak;casetypeid(uint32_t):// handle that casebreak;default:// handle that case}
TypeId: мне не удалось использовать typeid () на Arduino. Также typeid () является проверкой во время выполнения , а не во время компиляции, поэтому его нельзя использовать для генерации оптимизированного кода.
Дэн Чыонг
1
Да, нет, это не то, что вы думали. typeidпросто не может быть статической проверкой во время компиляции - по определению - так что это не способствует какой-либо оптимизации. For a template function, I need to special case the code based on the template variableИтак, что вам действительно нужно, так это статический полиморфизм через идиому CRTP. Именно это и достигается.
underscore_d
4
Не уверен, что мой ответ поможет.
Короткий ответ: вам действительно не нужно / не нужно знать тип переменной для ее использования.
Если вам нужно указать тип статической переменной, вы можете просто использовать auto.
В более сложном случае, когда вы хотите использовать «auto» в классе или структуре, я бы предложил использовать шаблон с decltype.
Например, предположим, что вы используете чью-то библиотеку и в ней есть переменная с именем «unknown_var», и вы хотите поместить ее в вектор или структуру, вы можете полностью сделать это:
template<typename T>struct my_struct {int some_field;
T my_data;};vector<decltype(unknown_var)> complex_vector;vector<my_struct<decltype(unknown_var)>> simple_vector
Надеюсь это поможет.
РЕДАКТИРОВАТЬ: Для хорошей оценки вот самый сложный случай, о котором я могу думать: наличие глобальной переменной неизвестного типа. В этом случае вам понадобится c ++ 14 и переменная шаблона.
Это все еще немного утомительно, но это максимально близко к безтиповым языкам. Просто убедитесь, что всякий раз, когда вы ссылаетесь на переменную шаблона, всегда помещайте туда спецификацию шаблона.
Вы определенно можете пойти туда, typeid(x).name()где x - имя переменной. Фактически он возвращает указатель const char на тип данных. Теперь посмотрим на следующий код.
#include<bits/stdc++.h>usingnamespace std;int main(){int n =36;char c ='A';double d =1.2;if(*(typeid(n).name())=='i'){
cout <<"I am an Integer variable"<< endl;}if(*((char*)typeid(d).name())=='d'){
cout <<"I am a Double variable"<< endl;}if(*((char*)typeid(c).name())=='c'){
cout <<"I am a Char variable"<< endl;}return0;}
Обратите внимание, как работают первый и второй оба варианта.
Распознавать тип по первому символу - очень плохая идея.
Дмитрий Кузьминов
Подскажите подробнее, Дмитрий? Я не понял твою точку зрения.
Пикачу
Это можно просто сократить до std::cout << "I'm a variable of type " << typeid(n).name(). (изменен, чтобы предотвратить появление артефактов, но это можно исправить с помощью другой проверки). Даже в этом случае, если вам абсолютно необходимо сравнение, это намного лучше сделатьtypeid(n) == typeid(int)
Ответы:
Вы можете использовать оператор typeid :
источник
i
значит целое число в вашем компиляторе. Возвращаемые имена не указаны стандартом.typeid
, очень сокращены, зависят от компилятора и не предназначены для использования человеком. Вы можете «разобрать» их (это настоящий термин!), Либо в коде с помощью чего-то вроде gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , с помощью таких утилит командной строки, какc++filt
, либо с помощью любого из различных онлайн-деманглеров например, demangler.com .Для статических утверждений введен C ++ 11,
decltype
который весьма полезен в определенных сценариях.источник
Если у вас есть переменная
Вы можете получить его тип, используя
См. Следующую ветку на SO: Аналогичный вопрос
источник
Основное различие между C ++ и Javascript заключается в том, что C ++ - это язык со статической типизацией, а javascript - динамический.
В языках с динамической типизацией переменная может содержать что угодно, и ее тип задается значением, которое она содержит, момент за моментом. В языках со статической типизацией тип переменной объявлен и не может быть изменен.
Может быть динамическая диспетчеризация и составление объектов и подтипирование (наследование и виртуальные функции), а также статическая диспетчеризация и супертипирование (через шаблон CRTP), но в любом случае тип переменной должен быть известен компилятору.
Если вы в состоянии не знать, что это такое или может быть, то это потому, что вы что-то спроектировали, поскольку язык имеет динамическую систему типов.
Если это так, вам лучше переосмыслить свой дизайн, поскольку он идет в землю, не естественную для используемого вами языка (больше всего похоже на движение по автостраде с гусеницей или по воде на машине).
источник
Обычно поиск типа переменной в C ++ - неправильный вопрос. Обычно это что-то, что вы носите с собой из процедурных языков, таких как, например, C или Pascal.
Если вы хотите закодировать разное поведение в зависимости от типа, попробуйте узнать, например, о перегрузке функций и наследовании объектов . Это не будет иметь смысла сразу после вашего первого дня изучения C ++, но продолжайте.
источник
Я считаю, что у меня есть допустимый вариант использования typeid (), так же как и sizeof (). Для функции шаблона мне нужен специальный код, основанный на переменной шаблона, чтобы я предлагал максимальную функциональность и гибкость.
Создание одного экземпляра функции для каждого поддерживаемого типа намного компактнее и удобнее, чем использование полиморфизма. Даже в этом случае я мог бы использовать этот трюк, чтобы написать тело функции только один раз:
Обратите внимание: поскольку в коде используются шаблоны, приведенный ниже оператор switch должен статически разрешаться только в один блок кода, оптимизируя все ложные случаи, AFAIK.
Рассмотрим этот пример, где нам может потребоваться обработать преобразование, если T относится к одному типу по сравнению с другим. Я использую его для специализации классов для доступа к оборудованию, где оборудование будет использовать тип myClassA или myClassB. При несовпадении мне нужно потратить время на преобразование данных.
источник
typeid
просто не может быть статической проверкой во время компиляции - по определению - так что это не способствует какой-либо оптимизации.For a template function, I need to special case the code based on the template variable
Итак, что вам действительно нужно, так это статический полиморфизм через идиому CRTP. Именно это и достигается.Не уверен, что мой ответ поможет.
Короткий ответ: вам действительно не нужно / не нужно знать тип переменной для ее использования.
Если вам нужно указать тип статической переменной, вы можете просто использовать auto.
В более сложном случае, когда вы хотите использовать «auto» в классе или структуре, я бы предложил использовать шаблон с decltype.
Например, предположим, что вы используете чью-то библиотеку и в ней есть переменная с именем «unknown_var», и вы хотите поместить ее в вектор или структуру, вы можете полностью сделать это:
Надеюсь это поможет.
РЕДАКТИРОВАТЬ: Для хорошей оценки вот самый сложный случай, о котором я могу думать: наличие глобальной переменной неизвестного типа. В этом случае вам понадобится c ++ 14 и переменная шаблона.
Что-то вроде этого:
Это все еще немного утомительно, но это максимально близко к безтиповым языкам. Просто убедитесь, что всякий раз, когда вы ссылаетесь на переменную шаблона, всегда помещайте туда спецификацию шаблона.
источник
источник
Если вам нужно провести сравнение между классом и известным типом, например:
Вы можете использовать эту строку сравнения:
который проверяет, что
typeid
имя содержит тип строки (имя typeid имеет другие искаженные данные, поэтому лучше использовать as1.find(s2)
вместо==
).источник
Вы определенно можете пойти туда,
typeid(x).name()
где x - имя переменной. Фактически он возвращает указатель const char на тип данных. Теперь посмотрим на следующий код.Обратите внимание, как работают первый и второй оба варианта.
источник
std::cout << "I'm a variable of type " << typeid(n).name()
. (изменен, чтобы предотвратить появление артефактов, но это можно исправить с помощью другой проверки). Даже в этом случае, если вам абсолютно необходимо сравнение, это намного лучше сделатьtypeid(n) == typeid(int)