Mengingat perhatian yang diterima pertanyaan / jawaban ini, dan umpan balik yang berharga dari GManNickG , saya telah sedikit membersihkan kode. Dua versi diberikan: satu dengan fitur C ++ 11 dan satu lagi dengan hanya fitur C ++ 98.
Dalam tipe file.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
Dalam file type.cpp (membutuhkan 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
Pemakaian:
#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;
}
Ini mencetak:
Type of ptr_base: Base*
Jenis pointee:Derived
Diuji dengan g ++ 4.7.2, g ++ 4.9.0 20140302 (eksperimental), clang ++ 3.4 (trunk 184647), clang 3.5 (trunk 202594) pada Linux 64 bit dan g ++ 4.7.2 (Mingw32, Win32 XP SP2).
Jika Anda tidak dapat menggunakan fitur C ++ 11, berikut adalah cara melakukannya di C ++ 98, file type.cpp sekarang:
#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
(Pembaruan dari 8 Sep 2013)
Jawaban yang diterima (per 7 Sep 2013) , ketika panggilan ke abi::__cxa_demangle()
berhasil, mengembalikan pointer ke array yang dialokasikan tumpukan lokal ... aduh!
Perhatikan juga bahwa jika Anda menyediakan buffer, abi::__cxa_demangle()
asumsikan buffer tersebut dialokasikan di heap. Mengalokasikan buffer pada tumpukan adalah bug (dari gnu doc): "Jika output_buffer
tidak cukup lama, ini akan diperluas menggunakan realloc
." Memanggil realloc()
penunjuk ke tumpukan ... aduh! (Lihat juga komentar baik Igor Skochinsky .)
Anda dapat dengan mudah memverifikasi kedua bug ini: cukup kurangi ukuran buffer dalam jawaban yang diterima (mulai 7 Sep 2013) dari 1024 menjadi sesuatu yang lebih kecil, misalnya 16, dan berikan sesuatu dengan nama tidak lebih dari 15 (begitu realloc()
juga tidak dipanggil). Namun, tergantung pada sistem Anda dan pengoptimalan compiler, outputnya adalah: sampah / nothing / program crash.
Untuk memverifikasi bug kedua: setel ukuran buffer ke 1 dan panggil dengan sesuatu yang namanya lebih dari 1 karakter. Ketika Anda menjalankannya, program hampir pasti macet saat mencoba memanggil realloc()
dengan pointer ke stack.
(Jawaban lama dari 27 Desember 2010)
Perubahan penting yang dibuat pada kode KeithB : buffer harus dialokasikan oleh malloc atau ditentukan sebagai NULL. JANGAN mengalokasikannya di tumpukan.
Sebaiknya periksa juga status itu.
Saya gagal menemukan HAVE_CXA_DEMANGLE
. Saya memeriksa __GNUG__
meskipun itu tidak menjamin bahwa kode bahkan akan dikompilasi. Ada yang punya ide yang lebih baik?
#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>
. Jika tidak bekerja dengan baik, terima kasih.