2011-11-03 46 views
17

Có cách nào để lấy thông tin typeid biên dịch từ GCC với RTTI bị vô hiệu hóa không? Trong Visual Studio, một lệnh đơn giản như const char* typeName = typeid(int).name(); sẽ trả về "int" một cách thích hợp, ngay cả khi RTTI bị tắt. Thật không may, GCC không thể làm như vậy. Khi tôi cố gắng gọi typeid mà không cần RTTI, chương trình của tôi bị treo. Tôi biết vô hiệu hóa RTTI không phải là một phần của tiêu chuẩn, nhưng có anyway tôi có thể buộc GCC để làm biên dịch thời gian giải quyết các loại được biết đến?Loại thời gian biên dịch không có RTTI với GCC

RTTI bị tắt vì lý do hiệu suất. Tôi không cần RTTI thời gian chạy.

Edit:

Đây là những gì tôi đã kết thúc đi với:

template<typename T> const char* TypeName(void); 
template<typename T> const char* TypeName(T type) { return TypeName<T>(); } 

#define REFLECTION_REGISTER_TYPE(type) \ 
    template <> const char* TypeName<type>(void) { return #type; } 

Nó đòi hỏi rằng REFLECTION_REGISTER_TYPE được gọi cho tất cả các loại cần thông tin phản ánh. Nhưng miễn là nó được gọi cho mọi loại yêu cầu, gọi TypeName<int> hoạt động hoàn hảo. Tôi cũng đã thêm hàm TypeName(T type) có nghĩa là bạn có thể làm những việc như sau: int x = 0; printf(TypeName(x)); và nó sẽ in ra "int". GCC thực sự có thể làm điều này tại thời gian biên dịch như VC++ có thể.

+1

lý do hiệu suất là gì bạn quan tâm? RTTI cơ bản là miễn phí, tiết kiệm một số chi phí kích thước nhị phân. –

+0

@Kyle: Trong g ++ với RTTI được bật, 'typeid (int) .name()' sẽ trả về "i" not "int". Điều đó có liên quan không? –

+0

@R. Martinho Fernandes: GCC có một số funcitons demangling có thể biến "i" thành "int". – Kyle

Trả lời

5

No. RTTI là Thời gian chạy Loại thông tin (và vô hiệu hóa nó là ngớ ngẩn, nhưng hey), và đó là mục đích của typeid. Nếu bạn muốn stringise loại tên tại thời gian biên dịch, bạn phải làm điều đó cho mình (thông qua mẫu hoặc macro).

+3

Tôi muốn làm một cái gì đó như thế này: 'struct S {int a, b; } const char * aType = typeid (S :: a) .name(); 'là tất cả thông tin thời gian biên dịch.Trong khi tôi chỉ đơn giản có thể xác định rằng 'a' là một' int', tôi muốn có trình biên dịch làm điều đó. Nó sẽ làm cho mã của tôi ít chi tiết hơn. VC trình biên dịch có thể làm điều đó, tôi đã không chắc chắn nếu có một cách để có được GCC để làm điều đó là tốt. – Kyle

+8

Tôi sẽ không bao giờ hiểu tại sao C++ không có tính năng này. Hữu ích hơn nhiều so với RTTI. – Pubby

1

GCC hỗ trợ toán tử loại thời gian biên dịch với typeof.

+3

Điều tôi thực sự cần là tên của loại. Nếu có cách nào đó để biến 'typeof' thành một chuỗi, điều đó sẽ hoàn hảo. – Kyle

+1

@Kyle: http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template – kennytm

+0

@KennyTM: Cảm ơn bạn đã liên kết. Điều đó đã kết thúc giống như giải pháp mà tôi nghĩ ra – Kyle

4

Trước hết, hãy bật lại RTTI.

Nếu không, nếu bạn thực sự * thực sự * cần có biểu diễn chuỗi không có nó, với thao tác chuỗi nhỏ và xem xét cẩn thận thực tế là bạn đang viết mã không chuẩn phá vỡ nếu bạn nâng cấp GCC, hoặc thay đổi nền tảng hoặc sử dụng một bộ tùy chọn khác, bạn có thể giả mạo nó.

#include <iostream> 
#include <string> 

std::string extract_type_name(const char* s) { 
    //add logic her 
    return s; 
} 

template<typename T> 
std::string type_name() { 
    static std::string s = extract_type_name(__PRETTY_FUNCTION__); 
    return s; 
} 

int main() { 
    std::cout << type_name<int>() << " " << type_name<std::string>() << std::endl; 
} 

Kết quả của chức năng đó trên ideone là

std::string type_name() [with T = int] 
std::string type_name() [with T = std::basic_string<char, std::char_traits<char>, std::allocator<char> >] 

Giả sử rằng __PRETTY_FUNCTION__ cư xử như nhau với RTTI tắt, giật ra các bit T = blah không nên quá khó khăn.

Ngoài ra, hãy nhớ rằng typeid(blah).name() cung cấp rất ít đảm bảo ... Tôi nhớ sử dụng nó trên một nền tảng mà kết quả cho bất kỳ loại người dùng được xác định chỉ đơn giản là struct. Không quá hữu ích. Dựa vào nó là mỏng manh ngay cả với RTTI bật [mà bạn nên làm dù sao đi nữa].

4

Có một giải pháp với những ưu và khuyết điểm của nó:

typedef void* TypeId; 
template<class T> 
TypeId TypeIdNoRTTI() //this function is instantiated for every different type 
{ 
    //WARNING: works only inside one module: same type coming from different module will have different value! 
    static T* TypeUniqueMarker = NULL; //thus this static variable will be created for each TypeIdNoRTTI<T> separately 
    return &TypeUniqueMarker; //it's address is unique identifier of TypeIdNoRTTI<T> type 
} 
Các vấn đề liên quan