2011-11-03 17 views
17

Esiste comunque la possibilità di ottenere le informazioni typeid in fase di compilazione da GCC con RTTI disabilitato? In Visual Studio, un comando semplice come const char* typeName = typeid(int).name(); restituirà "int" correttamente, anche se RTTI è disabilitato. Sfortunatamente, GCC non può fare lo stesso. Quando provo a chiamare typeid senza RTTI, il mio programma si arresta in modo anomalo. So che disabilitare RTTI non fa parte dello standard, ma è comunque possibile forzare GCC a eseguire la risoluzione temporale della compilazione di tipi noti?Tempo di compilazione typeid senza RTTI con GCC

RTTI è disabilitato per motivi di prestazioni. Non ho bisogno di runtime RTTI.

Edit:

Ecco quello che ho finito per andare con:

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

Richiede che REFLECTION_REGISTER_TYPE essere chiamato per ogni tipo che ha bisogno di informazioni riflessione. Ma finché viene chiamato per ogni tipo richiesto, chiamare TypeName<int> funziona perfettamente. Ho anche aggiunto la funzione TypeName(T type) che significa che puoi fare cose come questa: int x = 0; printf(TypeName(x)); e stamperà "int". GCC dovrebbe essere davvero in grado di farlo in fase di compilazione come può fare VC++.

+1

motivi di ciò che le prestazioni Siete preoccupati? RTTI è essenzialmente gratuito, salva un overhead di dimensioni binarie. –

+0

@Kyle: in g ++ con RTTI abilitato, 'typeid (int) .name()' restituirà "i" not "int". È rilevante? –

+0

@R. Martinho Fernandes: GCC ha alcune funzioni distruttive che possono trasformare "i" in "int". – Kyle

risposta

5

No. RTTI è RunTime Informazioni Tipo (e invalidante è stupido, ma hey), e questo è lo scopo della typeid. Se vuoi stringere i nomi dei tipi in fase di compilazione, devi farlo tu stesso (tramite template o macro).

+3

Mi piacerebbe fare qualcosa del genere: 'struct S {int a, b; } const char * aType = typeid (S :: a) .name(); 'che è tutto informazioni in fase di compilazione.Mentre posso semplicemente specificare che 'a' è un' int', preferirei che fosse il compilatore a farlo. Renderà il mio codice molto meno dettagliato. Il compilatore VC può farlo, non ero sicuro se ci fosse un modo per far sì che GCC lo facesse. – Kyle

+8

Non capirò mai perché C++ non ha questa caratteristica. Molto più utile di RTTI. – Pubby

1

GCC supporta l'operatore del tipo a tempo di compilazione con typeof.

+3

Quello di cui ho effettivamente bisogno è il nome del tipo. Se ci fosse in qualche modo girare 'typeof' in una stringa, sarebbe perfetto. – Kyle

+1

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

+0

@KennyTM: Grazie per questo link. Quello è finito come la soluzione che ho trovato – Kyle

4

Prima di tutto, riaccendere RTTI.

In mancanza di questo, se si veramente * veramente * bisogno di ottenere una rappresentazione di stringa di un tipo senza di essa, con un po 'di manipolazione delle stringhe, e un'attenta considerazione del fatto che si sta scrivendo il codice non standard che potrebbero interrompere se si aggiorna GCC, o cambiare piattaforme, o utilizzare un diverso set di opzioni, si potrebbe essere in grado di simulare.

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

L'uscita di tale funzione sulla 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> >] 

Supponendo che __PRETTY_FUNCTION__ comporta lo stesso con RTTI spento, tirando fuori il bit T = blah non dovrebbe essere troppo difficile.

Inoltre, tenere presente che typeid(blah).name() offre pochissime garanzie ... Ricordo di averlo utilizzato su una piattaforma in cui il risultato per qualsiasi tipo definito dall'utente era semplicemente struct. Non eccessivamente utile. Affidarsi a questo è fragile anche con RTTI attivato [che comunque dovresti fare].

4

C'è un'altra soluzione, con i suoi pro e contro:

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 
}