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.output_buffer
Wilayah memori, dialokasikan dengan malloc, dengan panjang * byte, tempat penyimpanan nama yang telah dipisahkan. Jika output_buffer tidak cukup panjang, maka akan diperluas menggunakan realloc. output_buffer bisa jadi NULL; dalam hal ini, nama yang telah didemangifikasi ditempatkan di wilayah memori yang dialokasikan dengan malloc.abi::__cxa_demangle
mengharapkannya untuk dialokasikan di heap. " Terima kasih banyak telah mencari dok!ret_val
terlempar selama konstruksi. Anda dapat menggunakan pelindung teropong untuk menjaganya.std::unique_ptr<char, decltype(&std::free)>
sebagai tanda tangan untuk pointer Anda.Inti pendorong berisi demangler. Checkout core / demangle.hpp :
Ini pada dasarnya hanya pembungkus untuk
abi::__cxa_demangle
, seperti yang telah disarankan sebelumnya.sumber
Inilah yang kami gunakan. HAVE_CXA_DEMANGLE hanya disetel jika tersedia (hanya GCC versi terbaru).
sumber
#include <cxxabi.h>
.Di sini, lihat type_strings.hpp yang berisi fungsi yang melakukan apa yang Anda inginkan.
Jika Anda hanya mencari alat demangling, yang misalnya dapat Anda gunakan untuk mengacaukan hal-hal yang ditampilkan dalam file log, lihatlah
c++filt
, yang disertakan dengan binutils. Itu dapat mendemangle C ++ dan nama simbol Java.sumber
abi::__cxa_demangle()
dan sejenisnya dari<cxxabi.h>
tidak spesifik GCC - mereka mungkin hanya GCC di masa lalu, tetapi pada saat posting ini ditulis,<cxxabi.h>
adalah standar ad-hoc yang mengakar. Jadi, meskipun tautan kode jawabannya adalah DOI, saya dapat menjamin bahwa Clang memberikan dukungan kelas satu dalam kasus ini… qv, dari sumber Clanglibcxxabi
: masing-masing menyatakan, impl, tes besar: git.io/vRTBo , git.io/vRTBh , git.io/vRTRf - komentar kode pengujian mencatat bahwa implementasi Clang mampu melakukan lebih banyak demangling, dibandingkan dengan GCC.Implementasinya telah ditentukan, jadi ini bukan sesuatu yang portabel. Di MSVC ++, name () adalah nama tanpa dekorasi, dan Anda harus melihat raw_name () untuk mendapatkan nama yang didekorasi.
Hanya sedikit dalam gelap di sini, tetapi di bawah gcc, Anda mungkin ingin melihat demangle.h
sumber
Bukan solusi lengkap, tetapi Anda mungkin ingin melihat apa yang ditentukan oleh beberapa makro standar (atau yang didukung secara luas). Ini umum dalam kode logging untuk melihat penggunaan makro:
sumber
Saya juga menemukan makro yang disebut
__PRETTY_FUNCTION__
, yang melakukan triknya. Ini memberi nama fungsi yang cantik (gambar :)). Inilah yang saya butuhkan.Yaitu memberi saya yang berikut:
Tapi menurut saya ini tidak berfungsi pada kompiler lain.
sumber
Sedikit variasi pada solusi Ali. Jika Anda ingin kodenya masih sangat mirip
typeid(bla).name()
,menulis ini sebagai gantinya
Typeid(bla).name()
(hanya berbeda dalam huruf kapital pertama)maka Anda mungkin tertarik dengan ini:
Dalam tipe file.hpp
type.cpp tetap sama seperti di solusi Ali
sumber
Lihatlah
__cxa_demangle
yang dapat Anda temukan dicxxabi.h
.sumber
sumber
The solusi yang diterima [1] kebanyakan bekerja dengan baik. Saya menemukan setidaknya satu kasus (dan saya tidak akan menyebutnya kasus sudut) yang tidak melaporkan apa yang saya harapkan ... dengan referensi.
Untuk kasus tersebut, saya menemukan solusi lain, diposting di bagian bawah.
Kasus bermasalah (menggunakan
type
seperti yang didefinisikan dalam [1]):menghasilkan
Solusi (menggunakan
type_name<decltype(obj)>()
, lihat kode di bawah):menghasilkan
seperti yang diinginkan (setidaknya oleh saya)
Kode . Itu harus dalam tajuk yang disertakan, bukan dalam sumber yang dikompilasi secara terpisah, karena masalah spesialisasi. Lihat referensi yang tidak ditentukan untuk fungsi template misalnya.
sumber
Saya selalu ingin menggunakan type_info, tetapi saya yakin bahwa hasil dari fungsi anggota name () tidak standar dan tidak akan selalu mengembalikan apa pun yang dapat diubah menjadi hasil yang bermakna.
Jika Anda menggunakan satu kompilator, mungkin ada fungsi khusus kompilator yang akan melakukan apa yang Anda inginkan. Periksa dokumentasinya.
sumber
Mengikuti solusi Ali, berikut adalah alternatif template C ++ 11 yang bekerja paling baik untuk penggunaan saya.
Pemakaian:
Akan mencetak:
sumber