この質問/回答が受け取る注意とGManNickGからの貴重なフィードバックを考慮して、コードを少しクリーンアップしました。2つのバージョンが提供されます。1つはC ++ 11機能を備え、もう1つはC ++ 98機能のみを備えています。
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
type.cppファイル(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
使用法:
#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;
}
それは印刷します:
ptr_baseのBase*
タイプ:指示先のタイプ:Derived
Linux 64ビット上のg ++ 4.7.2、g ++ 4.9.0 20140302(実験的)、clang ++ 3.4(トランク184647)、clang 3.5(トランク202594)およびg ++ 4.7.2(Mingw32、Win32 XP SP2)でテスト済み。
C ++ 11機能を使用できない場合、C ++ 98でこれを行う方法を次に示します。ファイルtype.cppは次のようになります。
#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
(2013年9月8日更新)
受け入れられた回答(2013年9月7日現在)への呼び出しabi::__cxa_demangle()
が成功すると、ローカルのスタック割り当て配列へのポインタが返されます ... ouch!
また、バッファーを提供する場合abi::__cxa_demangle()
は、ヒープ上に割り当てられていると想定します。スタックにバッファを割り当てることはバグです(GNUドキュメントから):「output_buffer
十分に長くない場合、それはを使用して拡張されrealloc
ます。」 スタックへのポインタを呼び出すrealloc()
...痛い!(Igor Skochinskyの親切なコメントも参照してください。)
単なる例16のために、より小さなものに1024年から(2013年9月7日の時点で)受け入れ答えにバッファサイズを小さくし、名前でそれに何かを与える:あなたは簡単にこれらのバグの両方を確認することができないので、(長い15以上realloc()
であります呼び出されません)。それでも、システムとコンパイラの最適化に応じて、出力は次のようになります。
2番目のバグを確認するには:バッファーサイズを1に設定し、名前が1文字より長いもので呼び出します。実行すると、プログラムrealloc()
はスタックへのポインタを使用して呼び出しを試みるため、ほぼ確実にクラッシュします。
(2010年12月27日の古い回答)
KeithBのコードに加えられた重要な変更:バッファーは、mallocによって割り当てられるか、NULLとして指定される必要があります。スタックに割り当てないでください。
そのステータスもチェックするのが賢明です。
見つけられませんでしたHAVE_CXA_DEMANGLE
。私はチェック__GNUG__
しますが、コードがコンパイルされることさえ保証していません。誰かがより良いアイデアを持っていますか?
#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>
。それ以外の場合は、うまくいきました。