2009-05-06 10 views
6

Czasami muszę nauczyć się typu wyrażenia podczas programowania w C lub C++. Czasami istnieje dobre IDE lub istniejąca dokumentacja, która mi pomoże, ale czasami nie. Często czuję, że taki konstrukt może być przydatny:Określanie typu wyrażenia

void (*myFunc)(int); 
printf("%s", nameoftype(myFunc)); //"void (*)(int)" 
int i, unsigned int u; 
printf("%s", nameoftype(i+u)); //"unsigned int" 

Jest to szczególnie prawdziwe w C++; think accessors obiektów const - czy zwracają odwołanie do const lub kopię? Zastanów się nad dynamicznymi rzutami i klasami wzorcowymi.

Jak mogę to zrobić? (ucz się typu wyrażenia)

Używam GCC, ale o ile mi wiadomo, nie ma takiego rozszerzenia. Sądzę więc, że jestem ciekawy jak ludzie rozwiązują ten problem. (Zadowalające są zarówno rozwiązania kompilacyjne, jak i runtime).

Odpowiedz

1

Czego szukasz? Automatyczne wnioskowanie o typie lub szukanie typu, aby można było poprawnie zadeklarować zmienną ręcznie? (twoje własne odpowiedzi wyglądają tak, jakbyś chciał mieć drugi). W tym przypadku, należy rozważyć użycie Geordi:

<litb> make type pointer to function taking pointer to array of 10 int returning void 
<geordi> void (*)(int (*)[10]) 

<litb> geordi: { int a = -1; unsigned int b = 0; cout << ETYPE(a + b), ETYPE_DESC(a + b), (a + b); } 
<geordi> rvalue unsigned int, rvalue unsigned integer, 4294967295 

<litb> geordi: << TYPE_DESC(void (*)(int (*)[10])) 
<geordi> pointer to a function taking a pointer to an array of 10 integers and returning nothing 

Automatyczna wnioskowanie nie jest obecnie możliwe bez bibliotek pomocniczych takich jak boost.typeof, które używają rozszerzenia kompilatora jak __typeof__ dla GCC. Następnie C++ otrzyma auto (z inną semantyką niż aktualny auto) i będzie w stanie to zrobić, wraz z decltype, aby uzyskać typ wyrażenia.

Jeśli można żyć z uzyskiwanie z kontekstu lokalnego, zawsze można utworzyć szablon funkcji takich jak to:

template<typename T> void f(T t) { /* ... */ } 
int main() { int a = -1; unsigned int b = 0; f(a + b); } 
+0

Przepraszam, myślałem, że to oczywiste, że nie szukałem inferencji typu. Chociaż nie mogę się doczekać, aby zobaczyć nowy kod sphagetti C++ 0x z automatycznymi zmiennymi dookoła :) - Wow, zapomniałem, że Geordi może pisać opisy. Przyjrzę się realizacji. Dziękuję również za link KDevelop. Może stanowić alternatywę dla Eclipse. – aib

+1

Link do Geordi jest martwy - oto aktualna lokalizacja na github: https://github.com/Eelis/geordi – KarlC

2

C++ ma operatora typeid;

typeid(expression).name() 

zwróci zdefiniowaną przez implementację nazwę typu wyrażenia. Niestety, zwykle nie jest to czytelne dla człowieka.

+3

Jeśli youare za pomocą g ++ jest to nazwa mangeled. Następnie możesz użyć narzędzia wiersza poleceń "C++ filt", aby je usunąć. –

+0

Ah, nigdy nie użyłem C++ filt. Zajrzę do tego, dzięki. – aib

+0

Obecnie to podejście nie jest zalecane i powinno być uważane w niektórych przypadkach za nieaktualne. Powód, dla którego drukowany jest typ, wyjście typu jest uciążliwe. Ponadto czasami drukuje nieprawidłowy typ! Dokładne przykłady są wyraźnie wyjaśnione w nowym "Skutecznym nowoczesnym C++", Rozdział 1, pozycja 4. – likern

13

Czasami po prostu zrobić:

int ***a = expression; 

i poszukaj "< typu ekspresyjnego > nie może być przypisany do wskaźnik do int^3" błąd. To wydaje się najbardziej przenośne obejście.

+1

Niektóre starsze kompilatory C faktycznie to jednak umożliwiają. :-( –

+3

Tworzę klasę "FailAssign", a następnie próbuję przypisać wyrażenie do instancji klasy, w ten sposób żadna automatyczna konwersja się nie zawiesza (nawet błędne) –

+2

Hmm, dobry pomysł.Chociaż moja droga pozwala ci zadeklarować potrójną wskazówkę! Jak często to robisz? :) – aib

1

Wypróbuj Boost.Typeof, aby sprawdzić, czy pasuje.

+0

Wydaje się, że jest to dobre rozwiązanie do wnioskowania o typie, ale nie widziałem makra, które się zwraca, lub funkcji, która zwraca ciąg zawierający nazwę typu. Można jednak dodać, że używa on centralnych makr REGISTER_(). – aib

Powiązane problemy