В C ++ как найти тип переменной?
В C ++ как найти тип переменной?
Ответы:
Вы можете использовать оператор typeid :
#include <typeinfo>
...
cout << typeid(variable).name() << endl;
i
значит целое число в вашем компиляторе. Возвращаемые имена не указаны стандартом.
typeid
, очень сокращены, зависят от компилятора и не предназначены для использования человеком. Вы можете «разобрать» их (это настоящий термин!), Либо в коде с помощью чего-то вроде gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , с помощью таких утилит командной строки, как c++filt
, либо с помощью любого из различных онлайн-деманглеров например, demangler.com .
Если у вас есть переменная
int k;
Вы можете получить его тип, используя
cout << typeid(k).name() << endl;
См. Следующую ветку на SO: Аналогичный вопрос
Основное различие между C ++ и Javascript заключается в том, что C ++ - это язык со статической типизацией, а javascript - динамический.
В языках с динамической типизацией переменная может содержать что угодно, и ее тип задается значением, которое она содержит, момент за моментом. В языках со статической типизацией тип переменной объявлен и не может быть изменен.
Может быть динамическая диспетчеризация и составление объектов и подтипирование (наследование и виртуальные функции), а также статическая диспетчеризация и супертипирование (через шаблон CRTP), но в любом случае тип переменной должен быть известен компилятору.
Если вы в состоянии не знать, что это такое или может быть, то это потому, что вы что-то спроектировали, поскольку язык имеет динамическую систему типов.
Если это так, вам лучше переосмыслить свой дизайн, поскольку он идет в землю, не естественную для используемого вами языка (больше всего похоже на движение по автостраде с гусеницей или по воде на машине).
Обычно поиск типа переменной в C ++ - неправильный вопрос. Обычно это что-то, что вы носите с собой из процедурных языков, таких как, например, C или Pascal.
Если вы хотите закодировать разное поведение в зависимости от типа, попробуйте узнать, например, о перегрузке функций и наследовании объектов . Это не будет иметь смысла сразу после вашего первого дня изучения C ++, но продолжайте.
Я считаю, что у меня есть допустимый вариант использования typeid (), так же как и sizeof (). Для функции шаблона мне нужен специальный код, основанный на переменной шаблона, чтобы я предлагал максимальную функциональность и гибкость.
Создание одного экземпляра функции для каждого поддерживаемого типа намного компактнее и удобнее, чем использование полиморфизма. Даже в этом случае я мог бы использовать этот трюк, чтобы написать тело функции только один раз:
Обратите внимание: поскольку в коде используются шаблоны, приведенный ниже оператор switch должен статически разрешаться только в один блок кода, оптимизируя все ложные случаи, AFAIK.
Рассмотрим этот пример, где нам может потребоваться обработать преобразование, если T относится к одному типу по сравнению с другим. Я использую его для специализации классов для доступа к оборудованию, где оборудование будет использовать тип myClassA или myClassB. При несовпадении мне нужно потратить время на преобразование данных.
switch ((typeid(T)) {
case typeid(myClassA):
// handle that case
break;
case typeid(myClassB):
// handle that case
break;
case typeid(uint32_t):
// handle that case
break;
default:
// handle that case
}
typeid
просто не может быть статической проверкой во время компиляции - по определению - так что это не способствует какой-либо оптимизации. For a template function, I need to special case the code based on the template variable
Итак, что вам действительно нужно, так это статический полиморфизм через идиому CRTP. Именно это и достигается.
Не уверен, что мой ответ поможет.
Короткий ответ: вам действительно не нужно / не нужно знать тип переменной для ее использования.
Если вам нужно указать тип статической переменной, вы можете просто использовать 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 и переменная шаблона.
Что-то вроде этого:
template<typename T> vector<T> global_var;
void random_func (auto unknown_var) {
global_var<decltype(unknown_var)>.push_back(unknown_var);
}
Это все еще немного утомительно, но это максимально близко к безтиповым языкам. Просто убедитесь, что всякий раз, когда вы ссылаетесь на переменную шаблона, всегда помещайте туда спецификацию шаблона.
Если вам нужно провести сравнение между классом и известным типом, например:
class Example{};
...
Example eg = Example();
Вы можете использовать эту строку сравнения:
bool isType = string( typeid(eg).name() ).find("Example") != string::npos;
который проверяет, что typeid
имя содержит тип строки (имя typeid имеет другие искаженные данные, поэтому лучше использовать a s1.find(s2)
вместо ==
).
Вы определенно можете пойти туда, typeid(x).name()
где x - имя переменной. Фактически он возвращает указатель const char на тип данных. Теперь посмотрим на следующий код.
#include<bits/stdc++.h>
using namespace 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;
}
return 0;
}
Обратите внимание, как работают первый и второй оба варианта.
std::cout << "I'm a variable of type " << typeid(n).name()
. (изменен, чтобы предотвратить появление артефактов, но это можно исправить с помощью другой проверки). Даже в этом случае, если вам абсолютно необходимо сравнение, это намного лучше сделатьtypeid(n) == typeid(int)