Với sự chú ý mà câu hỏi / câu trả lời này nhận được và phản hồi có giá trị từ GManNickG , tôi đã xóa mã một chút. Hai phiên bản được đưa ra: một với các tính năng C ++ 11 và một phiên bản khác chỉ có các tính năng C ++ 98.
Trong tệp 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
Trong tệp type.cpp (yêu cầu 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
Sử dụng:
#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;
}
Nó in:
Loại ptr_base: Base*
Loại điểm:Derived
Đã thử nghiệm với g ++ 4.7.2, g ++ 4.9.0 20140302 (thử nghiệm), clang ++ 3.4 (trung kế 184647), clang 3.5 (trung kế 202594) trên Linux 64 bit và g ++ 4.7.2 (Mingw32, Win32 XP SP2).
Nếu bạn không thể sử dụng các tính năng của C ++ 11, đây là cách nó có thể được thực hiện trong C ++ 98, tệp type.cpp bây giờ là:
#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
(Cập nhật từ ngày 8 tháng 9 năm 2013)
Câu trả lời được chấp nhận (kể từ ngày 7 tháng 9 năm 2013) , khi cuộc gọi đến abi::__cxa_demangle()
thành công, trả về một con trỏ đến một mảng được phân bổ ngăn xếp cục bộ ... ouch!
Cũng lưu ý rằng nếu bạn cung cấp bộ đệm, hãy abi::__cxa_demangle()
giả sử nó được cấp phát trên heap. Việc phân bổ bộ đệm trên ngăn xếp là một lỗi (từ gnu doc): "Nếu output_buffer
không đủ dài, nó sẽ được mở rộng bằng cách sử dụng realloc
." Đang gọi realloc()
một con trỏ tới ngăn xếp ... ouch! (Xem thêm bình luận tử tế của Igor Skochinsky .)
Bạn có thể dễ dàng xác minh cả hai lỗi: chỉ cần giảm kích thước bộ đệm trong câu trả lời được chấp nhận (tính đến 07 tháng 9 năm 2013) từ 1024 đến một cái gì đó nhỏ hơn, ví dụ 16, và cung cấp cho nó một cái gì đó với một tên không dài hơn 15 (do đó realloc()
là không được gọi). Tuy nhiên, tùy thuộc vào hệ thống của bạn và tối ưu hóa trình biên dịch, kết quả đầu ra sẽ là: rác / không có gì / sự cố chương trình.
Để xác minh lỗi thứ hai: đặt kích thước bộ đệm thành 1 và gọi nó bằng tên có tên dài hơn 1 ký tự. Khi bạn chạy nó, chương trình gần như chắc chắn bị treo khi nó cố gắng gọi realloc()
bằng con trỏ tới ngăn xếp.
(Câu trả lời cũ từ ngày 27 tháng 12 năm 2010)
Những thay đổi quan trọng được thực hiện đối với mã của KeithB : bộ đệm phải được cấp phát bởi malloc hoặc được chỉ định là NULL. KHÔNG phân bổ nó trên ngăn xếp.
Cũng nên kiểm tra trạng thái đó.
Tôi không tìm thấy HAVE_CXA_DEMANGLE
. Tôi kiểm tra __GNUG__
mặc dù điều đó không đảm bảo rằng mã sẽ được biên dịch. Bất cứ ai có một ý tưởng tốt hơn?
#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>
. Nếu không làm việc tuyệt vời, cảm ơn.