Como obtenho o tipo de uma variável?

130

Em C ++, como se encontra o tipo de uma variável?

0x499602D2
fonte
5
Possível duplicado de stackoverflow.com/questions/81870/print-variable-type-in-c
theharshest
7
cout << typeid (variável) .name () << endl;
SRN
2
Use a busca ou google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest é rápido: D
Kariboo
14
@Kariboo, eu usei o Google e ele me enviou aqui.
Michael Warner
Essa questão é muito incerta e até depois de ver as várias respostas; não é de forma alguma claro que a pergunta esteja buscando a resposta aceita.
Antti Haapala

Respostas:

157

Você pode usar o operador typeid :

#include <typeinfo>
...
cout << typeid(variable).name() << endl;
Rich O'Kelly
fonte
15
@ David - Então isignifica número inteiro no seu compilador. Os nomes retornados não são especificados pelo padrão.
Bo Persson
11
Quando eu o uso no vetor <int>, ele retorna St6vectorIiSaIiEE. WTF?
Boyan Kushlev
2
@BobbyBrown você não está sozinho !! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
Rich O'Kelly
5
Os nomes retornados por typeidsão muito abreviados, específicos do compilador e não se destinam ao consumo humano. Você pode "desmontá-las" (esse é o termo real!), Em código com algo como gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , com utilitários de linha de comando, como c++filtcom qualquer um dos vários desmanglers online como demangler.com .
Cincodenada
33

Para asserções estáticas, o C ++ 11 introduziu, o decltypeque é bastante útil em certos cenários.

Nae
fonte
12

Se você tem uma variável

int k;

Você pode obter esse tipo usando

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

Veja o seguinte tópico no SO: Pergunta semelhante

Amit
fonte
9

A principal diferença entre C ++ e Javascript é que C ++ é uma linguagem de tipo estático, enquanto o javascript é dinâmico.

Nas linguagens dinâmicas digitadas, uma variável pode conter qualquer coisa, e seu tipo é dado pelo valor que mantém, momento a momento. Nos idiomas estáticos, o tipo de uma variável é declarado e não pode ser alterado.

Pode haver despacho dinâmico e composição e subtipagem de objetos (herança e funções virtuais), bem como despacho estático e supertipagem (via modelo CRTP), mas, em qualquer caso, o tipo da variável deve ser conhecido pelo compilador.

Se você está em posição de não saber o que é ou poderia ser, é porque você projetou algo como a linguagem tem um sistema de tipos dinâmico.

Se for esse o caso, é melhor repensar o seu design, pois ele está indo para um terreno não natural para o idioma que você está usando (mais como ir em uma estrada com uma lagarta ou na água com um carro)

Emilio Garavaglia
fonte
Se o C ++ sofrer alterações dinâmicas, acho que seria ótimo e typeof e parseInt, as funções parseFloat também serão úteis, mas não sei por que os fabricantes de C ++ tornam isso muito difícil, por exemplo! que diz que seu bom para escrever cout << "String"
Waqas Tahir
determinação é melhor !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir
@Waqas Uh, o que? As pessoas que dizem que é melhor são as que definem o idioma e, na IMO, elas têm praticamente a palavra final em relação a isso - boas práticas de codificação, por exemplo. Você poderia reformular esse comentário para que faça mais sentido?
Fund Monica's Lawsuit
Eu discordo totalmente. Java, C #, PHP, Perl, Python e outros foram projetados em C e C ++ e não são lagartas. (Quando você cria um aplicativo de banco de dados para tabelas variáveis abertas de bancos de dados 'desconhecidos' você precisa tipo de campo de controle para o regime variável e vice-vera em um 'muito' maneira dymanic;))
TomeeNS
@TomeeNS: Não. Eles são escritos em C e C ++, não projetados . Eles são projetados para executar suas tarefas. Eles têm um tipo dinâmico, mesmo que C e C ++ não o façam. Isso não é nada estranho.
Emilio Garavaglia
8

Geralmente, querer encontrar o tipo de uma variável em C ++ é a pergunta errada. Tende a ser algo que você carrega de linguagens procedurais como, por exemplo, C ou Pascal.

Se você deseja codificar comportamentos diferentes, dependendo do tipo, tente aprender, por exemplo , sobrecarga de funções e herança de objetos . Isso não fará sentido imediato no seu primeiro dia de C ++, mas continue assim.

Pontus Gagge
fonte
Não, digamos que você tenha uma classe Object e uma subclasse Book. Agora imagine que você tem uma caixa que pode armazenar muitos objetos, mas, por algum motivo, deseja listar todos os livros dentro dela. Verificação do tipo é muito mais limpo depois ter que adicionar um método de "tipo" de objetos e, em seguida, substituí-lo no livro de retorno algo como "livro"
Paulo Cesar
Como em qualquer regra, há exceções (portanto, meu 'geralmente'!), E os contêineres tendem a adicionar complexidade à teoria dos tipos. Nunca me apaixonei demais por contêineres de objetos polimórficos ... na maioria dos casos, tipos uniformes de contêineres modelo são suficientes e são muito mais limpos.
Pontus Gagge
Você não usa modelos?
Bryan Grace
6

Acredito que tenho um caso de uso válido para usar typeid (), da mesma forma que é válido usar sizeof (). Para uma função de modelo, preciso especificar um caso especial do código com base na variável de modelo, para oferecer a máxima funcionalidade e flexibilidade.

É muito mais compacto e sustentável do que usar polimorfismo, criar uma instância da função para cada tipo suportado. Mesmo nesse caso, eu poderia usar esse truque para escrever o corpo da função apenas uma vez:

Observe que, como o código usa modelos, a instrução switch abaixo deve ser resolvida estaticamente em apenas um bloco de código, otimizando todos os casos falsos, AFAIK.

Considere este exemplo, onde podemos precisar manipular uma conversão se T for um tipo versus outro. Eu o uso para a especialização de classe para acessar o hardware em que o hardware usará o tipo myClassA ou myClassB. Em uma incompatibilidade, preciso gastar tempo convertendo os dados.

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
fonte
1
TypeId: Não pude usar typeid () no Arduino. Também typeid () é uma verificação de tempo de execução , não tempo de compilação, portanto não pode ser usado para gerar código otimizado.
precisa
1
Sim, não, isso não faz o que você pensou que fazia. typeidsimplesmente não pode ser uma verificação estática em tempo de compilação - por definição -, portanto, isso não facilita nenhuma otimização. For a template function, I need to special case the code based on the template variableCerto, então o que você realmente deseja é polimorfismo estático através do idioma CRTP. É exatamente o que isso alcança.
Underscore_d
4

Não tenho certeza se minha resposta ajudaria.

A resposta curta é que você realmente não precisa / deseja saber o tipo de variável para usá-la.

Se você precisar atribuir um tipo a uma variável estática, basta usar auto.

No caso mais sofisticado em que você deseja usar "auto" em uma classe ou estrutura, sugiro usar o modelo com decltype.

Por exemplo, digamos que você esteja usando a biblioteca de outra pessoa e ela possua uma variável chamada "unknown_var" e deseje colocá-la em um vetor ou estrutura, você pode fazer isso totalmente:

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

Espero que isto ajude.

EDIT: Para uma boa medida, aqui está o caso mais complexo que consigo pensar: ter uma variável global de tipo desconhecido. Nesse caso, você precisaria de c ++ 14 e variável de modelo.

Algo assim:

template<typename T> vector<T> global_var;

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

Ainda é um pouco tedioso, mas é o mais próximo possível dos idiomas sem fonte. Apenas certifique-se sempre que você referenciar a variável do modelo, sempre coloque a especificação do modelo lá.

gohongyi
fonte
2
#include <typeinfo>

...
string s = typeid(YourClass).name()
rad
fonte
0

Se você precisar fazer uma comparação entre uma classe e um tipo conhecido, por exemplo:

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

Você pode usar esta linha de comparação:

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

que verifica se o typeidnome contém o tipo de string (o nome typeid possui outros dados desconfigurados, é melhor fazer isso em s1.find(s2)vez de ==).

jackw11111
fonte
-2

Você pode definitivamente ir para typeid(x).name()onde x é o nome da variável. Na verdade, ele retorna um ponteiro const char para o tipo de dados. Agora, observe o seguinte código.

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

Observe como primeiro e segundo os dois se funcionam.

Pikachu
fonte
Reconhecer o tipo pelo primeiro caractere é uma péssima idéia.
Dmitry Kuzminov 21/01
Você pode ser mais específico, Dmitry? Não entendi seu ponto aqui.
Pikachu
Isso pode ser reduzido para std::cout << "I'm a variable of type " << typeid(n).name(). (reformulado para impedir artefatos a / an, mas isso pode ser corrigido com outra verificação). Mesmo assim, se você absolutamente deseja uma comparação, é muito melhor fazer issotypeid(n) == typeid(int)
Zoe