Comment obtenir le type d'une variable?

130

En C ++, comment trouver le type d'une variable?

0x499602D2
la source
5
Copie
7
cout << typeid (variable) .name () << endl;
SRN
2
Utilisez la recherche ou google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest est rapide: D
Kariboo
14
@Kariboo, j'ai utilisé Google et cela m'a envoyé ici.
Michael Warner
Cette question est très floue car elle est, et même après avoir vu les différentes réponses; il n'est en aucun cas clair que la question cherche la réponse acceptée.
Antti Haapala

Réponses:

158

Vous pouvez utiliser l'opérateur typeid :

#include <typeinfo>
...
cout << typeid(variable).name() << endl;
Rich O'Kelly
la source
15
@David - Donc isignifie entier sur votre compilateur. Les noms renvoyés ne sont pas spécifiés par la norme.
Bo Persson
11
Quand je l'utilise sur le vecteur <int>, il renvoie St6vectorIiSaIiEE. WTF?
Boyan Kushlev le
2
@BobbyBrown vous n'êtes pas seul !! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
Rich O'Kelly
5
Les noms renvoyés par typeidsont très abrégés, spécifiques au compilateur et ne sont pas destinés à la consommation humaine. Vous pouvez les «démêler» (c'est le terme réel!), Soit dans le code avec quelque chose comme gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , avec des utilitaires de ligne de commande tels que c++filt, ou avec l'un des différents démangleurs en ligne comme demangler.com .
cincodenada
33

Pour les assertions statiques, C ++ 11 a été introduit, decltypece qui est très utile dans certains scénarios.

Nae
la source
12

Si vous avez une variable

int k;

Vous pouvez obtenir son type en utilisant

cout << typeid(k).name() << endl;

Voir le fil de discussion suivant sur SO: Question similaire

Amit
la source
9

La principale différence entre C ++ et Javascript est que C ++ est un langage de type statique, alors que javascript est dynamique.

Dans les langages typés dynamiques, une variable peut contenir n'importe quoi, et son type est donné par la valeur qu'elle détient, instant par instant. Dans les langages à typage statique, le type d'une variable est déclaré et ne peut pas changer.

Il peut y avoir une répartition dynamique et une composition et un sous-typage d'objets (héritage et fonctions virtuelles) ainsi qu'une répartition statique et un sur-typage (via le modèle CRTP), mais dans tous les cas, le type de variable doit être connu du compilateur.

Si vous êtes en mesure de ne pas savoir ce que c'est ou ce que cela pourrait être, c'est parce que vous avez conçu quelque chose car le langage a un système de type dynamique.

Si tel est le cas, vous feriez mieux de repenser votre conception, car elle va dans un pays qui n'est pas naturel pour la langue que vous utilisez (la plupart comme aller sur une autoroute avec une chenille, ou dans l'eau avec une voiture)

Emilio Garavaglia
la source
Si C ++ change de dynamique, je pense que ce serait génial et que les fonctions de typeof et de parseInt, parseFloat seront également utiles, mais je ne sais pas pourquoi les fabricants de C ++ rendent les choses trop difficiles, par exemple! qui dit que c'est bon d'écrire cout << "String"
Waqas Tahir
la détermination est la meilleure !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir
@Waqas Euh, quoi? Les gens qui disent que c'est mieux sont ceux qui définissent la langue, et l'OMI, ils ont à peu près le dernier mot sur tout ce qui a à voir avec cela - de bonnes pratiques de codage, par exemple. Pourriez-vous reformuler ce commentaire pour qu'il ait plus de sens?
Fund Monica's Lawsuit
Je suis totalement en désaccord. Java, C #, PHP, Perl, Python et ainsi de suite ont été conçus en C et C ++ et ne sont pas des chenilles. (Lorsque vous créez une application de base de données pour ouvrir des tables de variables à partir de bases de données `` inconnues '', vous devez contrôler le type de champ vers le schéma de variables et vice-versa d'une manière `` très '' dymanique;))
TomeeNS
@TomeeNS: Non. Ils sont écrits en C et C ++, non conçus . Ils sont conçus pour faire leur travail.Ils ont un type dynamique même si C et C ++ eux-mêmes ne le font pas. Cela n'a rien d'étrange.
Emilio Garavaglia
8

En général, vouloir trouver le type d'une variable en C ++ est la mauvaise question. Cela a tendance à être quelque chose que vous emportez avec des langages procéduraux comme par exemple C ou Pascal.

Si vous souhaitez coder différents comportements en fonction du type, essayez d'en savoir plus sur la surcharge de fonctions et l' héritage d'objets . Cela n'aura pas de sens immédiat lors de votre premier jour de C ++, mais continuez.

Pontus Gagge
la source
Pas vraiment, disons que vous avez une classe Object et une sous-classe Book. Imaginez maintenant que vous avez une boîte qui peut stocker beaucoup d'objets, mais pour une raison quelconque, vous voulez lister tous les livres qu'elle contient. Vérifier le type est beaucoup plus propre que de devoir ajouter une méthode "type" à Object, puis la remplacer sur Book pour renvoyer quelque chose comme "book"
Paulo Cesar
Comme pour toute règle, il y a des exceptions (d'où mon «habituellement»!), Et les conteneurs ont tendance à ajouter de la complexité à la théorie des types. Je n'ai jamais été à la recherche de conteneurs d'objets polymorphes… dans la plupart des cas, les types de conteneurs uniformes basés sur des modèles suffisent et sont beaucoup plus propres.
Pontus Gagge
N'utilisez-vous pas de modèles?
Bryan Grace le
6

Je crois avoir un cas d'utilisation valide pour utiliser typeid (), de la même manière qu'il est valide d'utiliser sizeof (). Pour une fonction de modèle, j'ai besoin de cas particulier du code basé sur la variable de modèle, afin d'offrir un maximum de fonctionnalités et de flexibilité.

Il est beaucoup plus compact et maintenable que l'utilisation du polymorphisme, de créer une instance de la fonction pour chaque type pris en charge. Même dans ce cas, je pourrais utiliser cette astuce pour écrire le corps de la fonction une seule fois:

Notez que parce que le code utilise des modèles, l'instruction switch ci-dessous doit se résoudre statiquement en un seul bloc de code, optimisant ainsi tous les faux cas, AFAIK.

Considérez cet exemple, où nous pouvons avoir besoin de gérer une conversion si T est un type par rapport à un autre. Je l'utilise pour la spécialisation de classe pour accéder au matériel où le matériel utilisera le type myClassA ou myClassB. En cas d'incohérence, je dois passer du temps à convertir les données.

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
}
Dan Truong
la source
1
TypeId: Je n'ai pas pu utiliser typeid () sur Arduino. De plus, typeid () est une vérification à l' exécution , pas à la compilation, donc il ne peut pas être utilisé pour générer du code optimisé.
Dan Truong
1
Ouais, non, ça ne fait pas ce que tu pensais. typeidne peut tout simplement pas être une vérification statique à la compilation - par définition - donc cela ne facilite aucune optimisation. For a template function, I need to special case the code based on the template variableBon, donc ce que vous voulez vraiment, c'est le polymorphisme statique via l'idiome CRTP. C'est exactement ce que cela permet.
underscore_d
4

Je ne sais pas si ma réponse pourrait aider.

La réponse courte est que vous n'avez pas vraiment besoin / ne voulez pas connaître le type de variable pour l'utiliser.

Si vous avez besoin de donner un type à une variable statique, vous pouvez simplement utiliser auto.

Dans le cas plus sophistiqué où vous souhaitez utiliser "auto" dans une classe ou une structure, je suggérerais d'utiliser un template avec decltype.

Par exemple, disons que vous utilisez la bibliothèque de quelqu'un d'autre et qu'elle a une variable appelée "unknown_var" et que vous voudriez la mettre dans un vecteur ou une structure, vous pouvez totalement faire ceci:

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

J'espère que cela t'aides.

EDIT: Pour faire bonne mesure, voici le cas le plus complexe auquel je puisse penser: avoir une variable globale de type inconnu. Dans ce cas, vous aurez besoin de c ++ 14 et d'une variable de modèle.

Quelque chose comme ça:

template<typename T> vector<T> global_var;

void random_func (auto unknown_var) {
    global_var<decltype(unknown_var)>.push_back(unknown_var);
}

C'est toujours un peu fastidieux mais c'est aussi proche que possible des langages sans type. Assurez-vous simplement que chaque fois que vous faites référence à une variable de modèle, placez toujours la spécification de modèle ici.

gohongyi
la source
2
#include <typeinfo>

...
string s = typeid(YourClass).name()
rad
la source
0

Si vous avez besoin de faire une comparaison entre une classe et un type connu, par exemple:

class Example{};
...
Example eg = Example();

Vous pouvez utiliser cette ligne de comparaison:

bool isType = string( typeid(eg).name() ).find("Example") != string::npos;

qui vérifie que le typeidnom contient le type de chaîne (le nom de typeid a d'autres données mutilées, il est donc préférable de faire un s1.find(s2)au lieu de ==).

jackw11111
la source
-2

Vous pouvez certainement choisir typeid(x).name()où x est le nom de la variable. Il renvoie en fait un pointeur const char vers le type de données. Maintenant, regardez le code suivant.

#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;
}

Remarquez comment le premier et le second fonctionnent tous les deux.

Pikachu
la source
Reconnaître le type par le premier caractère est une très mauvaise idée.
Dmitry Kuzminov le
Pouvez-vous s'il vous plaît être Dmitry plus spécifique? Je n'ai pas compris votre point ici.
Pikachu le
Cela peut simplement être raccourci à std::cout << "I'm a variable of type " << typeid(n).name(). (reformulé pour éviter les artefacts / an, mais cela peut être corrigé avec une autre vérification). Même dans ce cas, si vous voulez absolument une comparaison, c'est tellement mieux à fairetypeid(n) == typeid(int)
Zoe