Dada la atención esta pregunta/respuesta recibe, y la retroalimentación valiosa de GManNickG, he limpiado el código un poco. Se dan dos versiones: una con características C++ 11 y otra con solo características C++ 98.
En el archivo tipo.HPP
#ifndef TYPE_HPP
#define TYPE_HPP
#include <string>
#include <typeinfo>
std::string demangle(const char* name);
template <class T>
std::string type(const T& t) {
return demangle(typeid(t).name());
}
#endif
En archivo type.cpp (requiere C++ 11)
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
Uso:
#include <iostream>
#include "type.hpp"
struct Base { virtual ~Base() {} };
struct Derived : public Base { };
int main() {
Base* ptr_base = new Derived(); // Please use smart pointers in YOUR code!
std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;
std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;
delete ptr_base;
}
Imprime:
Tipo de ptr_base: Base*
Tipo de pointee: Derived
probado con g ++ 4.7.2, g ++ 4.9.0 20140302 (experimental), sonido metálico ++ 3,4 (tronco 184 647), cling 3,5 (tronco 202.594) en Linux 64 bits y g ++ 4.7.2 (Mingw32, Win32 XP SP2).
Si no puede utilizar C++ 11 características, aquí es cómo se puede hacer en C++ 98, el archivo type.cpp es ahora:
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
struct handle {
char* p;
handle(char* ptr) : p(ptr) { }
~handle() { std::free(p); }
};
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
handle result(abi::__cxa_demangle(name, NULL, NULL, &status));
return (status==0) ? result.p : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
(actualización del 8 Sep, 2013)
The accepted answer (as of Sep 7, 2013), cuando la llamada a abi::__cxa_demangle()
tiene éxito, devuelve un puntero a una matriz asignada de pila local ... ¡ay!
También tenga en cuenta que si proporciona un búfer, abi::__cxa_demangle()
asume que debe asignarse en el montón. La asignación del búfer en la pila es un error (del doc. Gnu): "Si output_buffer
no es lo suficientemente largo, se expande usando realloc
."Llamando realloc()
en un puntero a la pila ... ¡ay! (Consulte también el comentario amable de Igor Skochinsky.)
Puede verificar fácilmente estos dos errores: simplemente reduzca el tamaño del búfer en la respuesta aceptada (a partir del 7 de septiembre de 2013) de 1024 a algo más pequeño, por ejemplo 16, y darle algo con un nombre no más largo que 15 (entonces realloc()
es no llamado llamado). Aún así, dependiendo de su sistema y las optimizaciones del compilador, el resultado será: basura/nada/bloqueo del programa.
Para verificar el segundo error: configure el tamaño del búfer en 1 y llámelo con algo cuyo nombre sea más largo que 1 carácter. Cuando lo ejecuta, el programa casi con seguridad se bloquea cuando intenta llamar al realloc()
con un puntero a la pila.
(La vieja respuesta del 27 Dic-2010)
cambios importantes realizados en KeithB's code: el buffer tiene que ser ya sea asignado por malloc o especificados como NULL. NO lo asigne en la pila.
Es sabio verificar ese estado también.
No pude encontrar HAVE_CXA_DEMANGLE
. Reviso __GNUG__
aunque eso no garantiza que el código siquiera se compile. Alguien tiene una mejor idea?
#include <cxxabi.h>
const string demangle(const char* name) {
int status = -4;
char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
const char* const demangled_name = (status==0)?res:name;
string ret_val(demangled_name);
free(res);
return ret_val;
}
Tenga en cuenta que esto necesita '' #include ''. De lo contrario, funcionó muy bien, gracias. –
jterrace
Ooops, lo siento. ¡Reparado y gracias! – Ali
¿Puede explicar por qué no se puede asignar el búfer en la pila? Porque hasta ahora funcionó bien para mí. – terminus