Angesichts der Aufmerksamkeit, die diese Frage / Antwort erhält, und des wertvollen Feedbacks von GManNickG habe ich den Code ein wenig aufgeräumt. Es werden zwei Versionen angegeben: eine mit C ++ 11-Funktionen und eine mit nur C ++ 98-Funktionen.
In der Datei type.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
In der Datei type.cpp (erfordert 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
Verwendung:
#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;
}
Es druckt:
Typ von ptr_base: Base*
Typ von Pointee:Derived
Getestet mit g ++ 4.7.2, g ++ 4.9.0 20140302 (experimentell), clang ++ 3.4 (Trunk 184647), clang 3.5 (Trunk 202594) unter Linux 64 Bit und g ++ 4.7.2 (Mingw32, Win32 XP SP2).
Wenn Sie nicht C ++ 11 - Funktionen verwenden können, hier ist , wie es in C ++ 98 durchgeführt werden kann, wird die Datei type.cpp ist jetzt:
#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
(Update vom 8. September 2013)
Die akzeptierte Antwort (Stand: 7. September 2013) gibt bei abi::__cxa_demangle()
erfolgreichem Aufruf von einen Zeiger auf ein lokales Array mit Stapelzuweisung zurück ... autsch!
Beachten Sie außerdem, dass bei der Bereitstellung eines Puffers abi::__cxa_demangle()
davon ausgegangen wird, dass dieser auf dem Heap zugewiesen ist. Das Zuweisen des Puffers auf dem Stapel ist ein Fehler (aus dem Gnu-Dokument): "Wenn output_buffer
es nicht lang genug ist, wird es mit erweitert realloc
." Der Aufruf realloc()
auf einen Zeiger auf den Stapel ... autsch! (Siehe auch Igor Skochinskys freundlichen Kommentar.)
Sie können diese beiden Fehler leicht überprüfen: Reduzieren Sie einfach die Puffergröße in der akzeptierten Antwort (Stand: 7. September 2013) von 1024 auf etwas Kleineres, z. B. 16, und geben Sie etwas mit einem Namen an, der nicht länger als 15 ist (so realloc()
ist es auch) nicht genannt). Abhängig von Ihrem System und den Compiler-Optimierungen lautet die Ausgabe jedoch: Garbage / Nothing / Program Crash.
So überprüfen Sie den zweiten Fehler: Setzen Sie die Puffergröße auf 1 und rufen Sie sie mit etwas auf, dessen Name länger als 1 Zeichen ist. Wenn Sie es ausführen, stürzt das Programm fast sicher ab, wenn es versucht, realloc()
mit einem Zeiger auf den Stapel aufzurufen .
(Die alte Antwort vom 27. Dezember 2010)
Wichtige Änderungen am KeithB-Code : Der Puffer muss entweder von malloc zugewiesen oder als NULL angegeben werden. Ordnen Sie es NICHT dem Stapel zu.
Es ist ratsam, auch diesen Status zu überprüfen.
Ich konnte nicht finden HAVE_CXA_DEMANGLE
. Ich überprüfe, __GNUG__
obwohl dies nicht garantiert, dass der Code überhaupt kompiliert wird. Hat jemand eine bessere Idee?
#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;
}
#include <cxxabi.h>
. Ansonsten hat super geklappt, danke.