Use o operador typeid em C++
Este artigo explica e demonstra como utilizar o operador typeid
em C++.
Use o operador typeid
para recuperar o nome do tipo do objeto em C++
Você pode usar o operador typeid
para recuperar as informações de tipo de uma determinada expressão ou objeto. Ele retorna uma referência ao tipo de biblioteca padrão std::type_info
, que é definido em um cabeçalho <typeinfo>
.
O objeto std::type_info
tem a função de membro name
que você pode utilizar para retornar uma cadeia de caracteres que descreve o tipo subjacente do objeto de argumento. Observe que as informações de tipo recuperadas por typeid
dependem da implementação. Ou seja, os compiladores mais comuns gcc
e clang
retornam nomes mutilados, conforme demonstrado no próximo exemplo de código.
Outras implementações, como o Microsoft Visual C++, exibem informações em formas mais legíveis. Ainda assim, lembre-se de que você ainda pode aprender a identificar os nomes dos tipos integrados exibidos pela implementação anterior. Por exemplo, o objeto int
retorna um caractere i
e um ponteiro para o objeto int
retorna uma cadeia de caracteres Pi
.
#include <iostream>
#include <string>
#include <typeinfo>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
int i1 = 1234;
string str1("arbitrary string");
auto ptr = &i1;
cout << "i1 type: " << typeid(i1).name() << '\n'
<< "str1 type: " << typeid(str1).name() << '\n'
<< "ptr type: " << typeid(ptr).name() << endl;
const std::type_info& r1 = typeid(i1);
cout << '\n' << "i1 type: " << r1.name() << '\n';
return EXIT_SUCCESS;
}
Resultado:
i1 type : i str1 type
: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE ptr type
: Pi
i1 type : i
Por outro lado, se chamarmos o comando typeid
em referências a objetos, descobriremos que as informações de tipo recuperadas nem sempre são precisas e às vezes muito enigmáticas para serem legíveis. O exemplo a seguir mostra um caso em que a segunda chamada para o operador typeid
retorna as informações de tipo incorretamente.
#include <iostream>
#include <string>
#include <typeinfo>
using std::cout;
using std::endl;
struct Base {};
struct Derived : Base {};
struct Base2 {
virtual void foo() {}
};
struct Derived2 : Base2 {};
int main() {
Derived d1;
Base& b1 = d1;
cout << "non-polymorphic base: " << typeid(b1).name() << '\n';
Derived2 d2;
Base2& b2 = d2;
cout << "polymorphic base: " << typeid(b2).name() << '\n';
return EXIT_SUCCESS;
}
Resultado:
non - polymorphic base : 4Base polymorphic base : 8Derived2
Esse comportamento pode ser corrigido usando a função de biblioteca Boost TypeIndex, type_id_with_cvr
, que pode retornar as informações de tipo com precisão. Geralmente, os objetos com os modificadores const
, volatile
, &
e &&
causam a informação de tipo incorreta quando o operador typeid
é usado; portanto, você deve confiar melhor na função type_id_with_cvr
.
O exemplo de código a seguir requer que a biblioteca Boost seja instalada no sistema e a função type_id_with_cvr
está sob o namespace boost::typeindex
.
#include <boost/type_index.hpp>
#include <iostream>
#include <string>
#include <typeinfo>
using boost::typeindex::type_id_with_cvr;
using std::cout;
using std::endl;
struct Base {};
struct Derived : Base {};
struct Base2 {
virtual void foo() {}
};
struct Derived2 : Base2 {};
int main() {
Derived d1;
Base& b1 = d1;
Derived2 d2;
Base2& b2 = d2;
cout << type_id_with_cvr<decltype(b1)>().pretty_name() << '\n';
cout << type_id_with_cvr<decltype(b2)>().pretty_name() << '\n';
return EXIT_SUCCESS;
}
Resultado:
Base & Base2&
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook