2011-11-03 113 views
17

有沒有辦法從GCC獲取編譯時typeid的信息,RTTI禁用?在Visual Studio下,一個簡單的命令如const char* typeName = typeid(int).name();將適當地返回「int」,即使RTTI被禁用。不幸的是,GCC不能這樣做。當我嘗試在沒有RTTI的情況下撥打typeid時,我的程序崩潰。我知道禁用RTTI不是標準的一部分,但無論如何,我可以強制GCC編譯已知類型的時間分辨率嗎?使用GCC編譯時間typeid而沒有RTTI

由於性能原因,RTTI被禁用。我不需要運行時RTTI。

編輯:

這裏是我結束了去:

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; } 

它要求REFLECTION_REGISTER_TYPE堪稱爲每個需要反思信息類型。但只要它需要每種所需的類型,撥打TypeName<int>就能完美工作。我還添加了功能TypeName(T type)這意味着你可以做這樣的事情:int x = 0; printf(TypeName(x));它會打印出「int」。 GCC應該能夠像VC++一樣在編譯時做到這一點。

+1

什麼性能方面的原因你關心? RTTI本質上是免費的,節省一些二進制大小的開銷。 –

+0

@Kyle:在啓用了RTTI的g ++中,'typeid(int).name()'將返回「i」而不是「int」。這是相關的嗎? –

+0

@R。 Martinho Fernandes:海灣合作委員會有一些可以將「我」變成「int」的解除功能。 – Kyle

回答

5

編號RTTI是運行時間類型信息(並禁用它很愚蠢,但嘿),這就是typeid的目的。如果你想在編譯時將字符串名稱串起來,你必須自己做(通過模板或宏)。

+3

我想要做這樣的事情:struct S {int a,b; } const char * aType = typeid(S :: a).name();'這是所有編譯時間信息。雖然我可以簡單地指定'a'是一個'int',我寧願讓編譯器去做。這將使我的代碼更加冗長。 VC編譯器可以做到這一點,我不確定是否有辦法讓GCC也這樣做。 – Kyle

+8

我永遠不會明白爲什麼C++沒有這個特性。比RTTI更有用。 – Pubby

1

GCC支持編譯時運算符typeof

+3

我真正需要的是類型的名稱。如果有人把'typeof'變成一個字符串,那就完美了。 – Kyle

+1

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

+0

@KennyTM:感謝您的鏈接。這最終成爲我想出的解決方案 – Kyle

4

首先,打開RTTI。

如果做不到這一點,如果你真的*真的*需要得到一個類型的字符串表示沒有它,用少許字符串操作,並認真考慮的是你寫的非標準代碼的事實,可能如果升級GCC或更換平臺,或者使用其他選項,則可能會造成僞造。

#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; 
} 

上ideone該函數的輸出是

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

假設__PRETTY_FUNCTION__行爲相同與RTTI截止,猛拉出T = blah位不應過於困難。

此外,請記住typeid(blah).name()提供了很少的保證......我記得在一個平臺上使用它,任何用戶定義類型的結果只是struct。不太有用。依靠它,即使在RTTI打開的情況下也是脆弱的[你應該做任何事情]。

4

有其利弊另一種解決方案:

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 
}