2011-11-03 11 views
17

Czy mimo to można uzyskać informację o kompilacji typeid z GCC z wyłączonym RTTI? Pod Visual Studio, proste polecenie, takie jak const char* typeName = typeid(int).name(); odpowiednio zwróci "int", nawet jeśli RTTI jest wyłączone. Niestety GCC nie może zrobić tego samego. Kiedy próbuję wywołać typeid bez RTTI, mój program ulega awarii. Wiem, że wyłączenie RTTI nie jest częścią standardu, ale czy mimo to mogę wymusić GCC, aby wykonał kompilację czasową znanych typów?Czas kompilacji typeid bez RTTI z GCC

Usługa RTTI jest wyłączona ze względu na wydajność. Nie potrzebuję RTTI środowiska wykonawczego.

Edit:

Oto co się dzieje z zakończonych:

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

Wymaga ona REFLECTION_REGISTER_TYPE nazwać dla każdego typu, który potrzebuje informacji refleksji. Ale tak długo, jak jest to wymagane dla każdego wymaganego typu, wywołanie TypeName<int> działa idealnie. Dodałem także funkcję TypeName(T type), co oznacza, że ​​możesz wykonać następujące czynności: int x = 0; printf(TypeName(x)); i wydrukuje "int". GCC powinien naprawdę być w stanie to zrobić w czasie kompilacji, tak jak VC++.

+1

powody Co wydajność Czy jesteś zaniepokojony? RTTI jest w zasadzie bezpłatny, oszczędzając na binarnym obciążeniu. –

+0

@Kyle: W g ++ z włączonym RTTI, 'typeid (int) .name()' zwróci "i" nie "int". Czy to jest istotne? –

+0

@R. Martinho Fernandes: GCC ma kilka funkcji demangowania, które mogą zmienić "i" w "int". – Kyle

Odpowiedz

5

Nr RTTI to RunTime Informacja o typie (i wyłączenie go jest głupie, ale hej), i to jest celem typeid. Jeśli chcesz sklasyfikować nazwy typów w czasie kompilacji, musisz zrobić to sam (za pomocą szablonu lub makr).

+3

Chciałbym zrobić coś takiego: 'struct S {int a, b; } const char * aType = typeid (S :: a) .name(); 'który jest informacją o czasie kompilacji.Chociaż mogę po prostu określić, że 'a' jest' int', wolałbym, żeby kompilator to zrobił. To sprawi, że mój kod będzie mniej gadatliwy. Kompilator VC może to zrobić, nie byłem pewien, czy istnieje sposób, aby GCC również to zrobił. – Kyle

+8

Nigdy nie zrozumiem, dlaczego C++ nie ma tej funkcji. O wiele bardziej przydatny niż RTTI. – Pubby

1

GCC obsługuje operator czasu kompilacji z typeof.

+3

Tym, czego naprawdę potrzebuję, jest nazwa typu. Gdyby był jakiś sposób, aby włączyć 'typof' w łańcuch, byłoby idealnie. – Kyle

+1

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

+0

@KennyTM: Dzięki za ten link. To było jak rozwiązanie, które wymyśliłem – Kyle

4

Po pierwsze, włącz ponownie RTTI.

Jeśli nie, naprawdę * naprawdę * trzeba uzyskać reprezentację ciągów typu bez niego, z małą manipulacją ciągami i starannym rozważeniem faktu, że piszesz niestandardowy kod, który może przerwać, jeśli uaktualnisz GCC, zmienisz platformy lub użyjesz innego zestawu opcji, możesz go sfałszować.

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

Wyjście z tej funkcji na ideone jest

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

Zakładając, że __PRETTY_FUNCTION__ zachowuje się tak samo z RTTI wyłączony, szarpiąc się z T = blah kawałek nie powinno być zbyt trudne.

Należy również pamiętać, że typeid(blah).name() oferuje bardzo niewiele gwarancji ... Pamiętam, że używam go na jednej platformie, gdzie wynik dla dowolnego typu zdefiniowanego przez użytkownika był po prostu struct. Niezbyt przydatne. Poleganie na nim jest słabe nawet przy włączonym RTTI [co powinieneś zrobić w każdym razie].

4

Jest inne rozwiązanie z jego zalet i wad:

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 
}