Як у 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 ++ є мовою статичного типу, wile javascript - динамічним.
У динамічних набраних мовах змінна може містити будь-яку річ, а її тип задається значенням, яке вона має, мить за моментом. У мовах, що набираються статично, тип змінної оголошується і не може змінюватися.
Тут можуть бути динамічна диспетчеризація та композиція об'єктів та підтипів (успадкування та віртуальні функції), а також статична диспетчеризація та властивість (через шаблон CRTP), але у будь-якому випадку тип змінної повинен бути відомий компілятору.
Якщо ви не можете знати, що це таке, чи може бути, це тому, що ви створили щось, оскільки мова має динамічну систему типу.
Якщо це так, вам краще переосмислити свій дизайн, оскільки він йде в землю, не природну для мови, якою ви користуєтесь (найбільше, як їхати по автостраді з гусеницею або у воді з машиною)
Зазвичай, бажати знайти тип змінної в C ++ - це неправильне питання. Це, як правило, щось, що ви використовуєте з процедурних мов, наприклад, C або Pascal.
Якщо ви хочете кодувати різні форми поведінки залежно від типу, спробуйте дізнатися, наприклад, про перевантаження функцій та успадкування об'єктів . Це не матиме негайного сенсу у ваш перший день C ++, але продовжуйте це.
Я вважаю, що у мене є дійсний випадок використання для використання typeid (), так само, як і для sizeof (). Для функції шаблону мені потрібно виділити особливий регістр коду на основі змінної шаблону, щоб я запропонував максимальну функціональність та гнучкість.
Набагато більш компактне і бездоганне, ніж використання поліморфізму, створити один екземпляр функції для кожного підтримуваного типу. Навіть у такому випадку я міг би скористатися цим трюком, щоб записати тіло функції лише один раз:
Зауважте, що оскільки в коді використовуються шаблони, викладений нижче переклад повинен статично вирішуватися лише в один блок коду, оптимізуючи всі помилкові випадки, 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" в класі або структурі, я б запропонував використовувати шаблон з 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
Сподіваюся, це допомагає.
EDIT: На жаль, ось найскладніший випадок, про який я можу придумати: наявність глобальної змінної невідомого типу. У цьому випадку вам знадобиться 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 має інші зведені дані, тому найкраще робити 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)