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.
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)
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.
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)){casetypeid(myClassA):// handle that casebreak;casetypeid(myClassB):// handle that casebreak;casetypeid(uint32_t):// handle that casebreak;default:// handle that case}
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.
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á.
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>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;}
Observe como primeiro e segundo os dois se funcionam.
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)
Respostas:
Você pode usar o operador typeid :
fonte
i
significa número inteiro no seu compilador. Os nomes retornados não são especificados pelo padrão.typeid
sã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, comoc++filt
com qualquer um dos vários desmanglers online como demangler.com .Para asserções estáticas, o C ++ 11 introduziu, o
decltype
que é bastante útil em certos cenários.fonte
Se você tem uma variável
Você pode obter esse tipo usando
Veja o seguinte tópico no SO: Pergunta semelhante
fonte
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)
fonte
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.
fonte
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.
fonte
typeid
simplesmente 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 variable
Certo, então o que você realmente deseja é polimorfismo estático através do idioma CRTP. É exatamente o que isso alcança.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:
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:
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á.
fonte
fonte
Se você precisar fazer uma comparação entre uma classe e um tipo conhecido, por exemplo:
Você pode usar esta linha de comparação:
que verifica se o
typeid
nome contém o tipo de string (o nome typeid possui outros dados desconfigurados, é melhor fazer isso ems1.find(s2)
vez de==
).fonte
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.Observe como primeiro e segundo os dois se funcionam.
fonte
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)