Załóżmy, że mamy kilka nazwanych wyliczeń:
enum MyEnum {
FOO,
BAR = 0x50
};
To, co wyszukałem w Google, to skrypt (w dowolnym języku), który skanuje wszystkie nagłówki w moim projekcie i generuje nagłówek z jedną funkcją na wyliczenie.
char* enum_to_string(MyEnum t);
I implementacja z czymś takim:
char* enum_to_string(MyEnum t){
switch(t){
case FOO:
return "FOO";
case BAR:
return "BAR";
default:
return "INVALID ENUM";
}
}
Gotcha jest tak naprawdę z wyliczeniami zdefiniowanymi przez typ i nienazwanymi wyliczeniami w stylu C. Czy ktoś coś na to wie?
EDYCJA: Rozwiązanie nie powinno modyfikować mojego źródła, z wyjątkiem wygenerowanych funkcji. Wyliczenia znajdują się w API, więc korzystanie z rozwiązań proponowanych do tej pory nie wchodzi w grę.
Odpowiedzi:
Możesz wypróbować GCCXML .
Uruchomienie GCCXML na przykładowym kodzie daje:
Możesz użyć dowolnego preferowanego języka, aby wyciągnąć tagi Enumeration i EnumValue i wygenerować żądany kod.
źródło
X-makra to najlepsze rozwiązanie. Przykład:
colours.def:
Jednak zazwyczaj wolę następującą metodę, aby można było nieco poprawić ciąg.
źródło
#define X(a, b) #b
. Jest to konieczne tylko wtedy, gdy definicja wygląda takX(Red, red)
, a nie definicja pokazana w odpowiedzi,X(Red, "red")
@hydroo: Bez dodatkowego pliku:
źródło
MetaSyntacticVariableNames[]
być częścią deklaracji klasy, tworząc metodęstatic const char* getNameByEnum(MetaSyntacticVariable e) { /*code to return the static string*/ }
Zwykle tworzę tablicę C z nazwami w tej samej kolejności i pozycji, co wartości wyliczenia.
na przykład.
wtedy możesz użyć tablicy w miejscach, w których potrzebujesz wartości czytelnej dla człowieka, np
Możesz trochę poeksperymentować z operatorem stringizing (patrz # w Twoim opisie preprocesora), który zrobi to, co chcesz, w pewnych okolicznościach - np .:
wypisze "czerwony" na standardowe wyjście. Niestety to nie zadziała dla zmiennej (ponieważ otrzymasz wydrukowaną nazwę zmiennej)
źródło
Mam niezwykle proste w użyciu makro, które robi to w całkowicie SUCHY sposób. Obejmuje różnorodne makra i prostą magię parsowania. Tutaj idzie:
Aby użyć tego w swoim kodzie, po prostu wykonaj:
źródło
QT jest w stanie wyciągnąć to z (dzięki kompilatorowi meta obiektu):
Źródło
źródło
Można to zrobić w C ++ 11
źródło
Właśnie dzisiaj ponownie wymyśliłem to koło i pomyślałem, że się nim podzielę.
Ta implementacja nie wymaga żadnych zmian w kodzie, który definiuje stałe, którymi mogą być wyliczenia,
#define
s lub cokolwiek innego, co przechodzi do liczby całkowitej - w moim przypadku miałem symbole zdefiniowane w kategoriach innych symboli. Działa również dobrze z rzadkimi wartościami. Pozwala nawet na wiele nazw dla tej samej wartości, zwracając zawsze pierwszą. Jedynym minusem jest to, że wymaga to utworzenia tabeli stałych, które mogą stać się nieaktualne, gdy na przykład zostaną dodane nowe.Przykład tego, jak go użyjesz:
IdToName
Funkcja polega nastd::lower_bound
robić szybkich wyszukiwań, co wymaga tabelę być posortowane. Jeśli pierwsze dwa wpisy w tabeli nie są w kolejności, funkcja posortuje je automatycznie.Edycja: komentarz sprawił, że pomyślałem o innym sposobie wykorzystania tej samej zasady. Makro upraszcza generowanie dużej
switch
instrukcji.źródło
switch and case
ponieważ jest to proste i łatwe do zrozumienia.Dalsza dyskusja na temat tej metody
Triki z dyrektywami preprocesora dla nowych użytkowników
źródło
Ciekawe, aby zobaczyć, ile sposobów. oto jeden, którego użyłem dawno temu:
w pliku myenummap.h:
w main.cpp
To nie jest stała, ale wygodna.
Oto inny sposób korzystania z funkcji C ++ 11. To jest const, nie dziedziczy kontenera STL i jest trochę bardziej uporządkowane:
źródło
Stosowanie:
źródło
MyEnum x = MyEnum::TWO;
. Opublikowałem swoją edycję Twojej klasy, aby to wesprzeć.Rozwiązanie makro Sumy jest fajne. Nie musisz jednak mieć dwóch różnych makr. C ++ na szczęście dwa razy dołączy nagłówek. Po prostu pomiń osłonę włączającą.
Więc miałbyś foobar.h definiujący tylko
i umieściłbyś to w ten sposób:
enumfactory.h zrobi 2
#include ENUMFACTORY_ARGUMENT
s. W pierwszej rundzie ENUM rozszerza się jak sumaDECLARE_ENUM
; w drugiej rundzie ENUM działa jakDEFINE_ENUM
.Możesz dołączyć enumfactory.h również wiele razy, o ile przekazujesz różne # define's dla ENUMFACTORY_ARGUMENT
źródło
Zwróć uwagę, że najlepiej byłoby, gdyby funkcja konwersji zwracała const char *.
Jeśli możesz sobie pozwolić na umieszczanie wyliczeń w oddzielnych plikach nagłówkowych, możesz zrobić coś takiego z makrami (o, to będzie brzydkie):
Gdzie enum_def.h ma:
A enum_conv.h ma:
I wreszcie colour.h ma:
I możesz użyć funkcji konwersji jako:
To jest brzydkie, ale jest to jedyny sposób (na poziomie preprocesora), który pozwala zdefiniować wyliczenie tylko w jednym miejscu w kodzie. Twój kod nie jest zatem podatny na błędy spowodowane modyfikacjami wyliczenia. Twoja definicja wyliczenia i funkcja konwersji będą zawsze zsynchronizowane. Jednak powtarzam, to jest brzydkie :)
źródło
Inna odpowiedź: w niektórych kontekstach sensowne jest zdefiniowanie wyliczenia w formacie niekodowym, takim jak plik CSV, YAML lub XML, a następnie wygenerowanie zarówno kodu wyliczenia C ++, jak i kodu ciągu na podstawie definicji. Takie podejście może być praktyczne w Twojej aplikacji lub nie, ale warto o tym pamiętać.
źródło
To jest modyfikacja odpowiedzi @ user3360260. Posiada następujące nowe funkcje
MyEnum fromString(const string&)
wsparcieStosowanie:
Oto kod
Zauważ, że konwersja toString to szybkie wyszukiwanie, podczas gdy konwersja fromString to powolne wyszukiwanie liniowe. Ale łańcuchy i tak są tak drogie (i związane z nimi IO), że nie czułem potrzeby optymalizacji lub używania bimapy.
źródło
Tutaj rozwiązanie jednoplikowe (oparte na eleganckiej odpowiedzi @Marcin:
źródło
Robię to z oddzielnymi klasami opakowującymi wyliczenia obok siebie, które są generowane za pomocą makr. Jest kilka zalet:
Wadą jest oczywiście to, że muszę zduplikować wartości wyliczenia w klasach programu formatującego i nie mam żadnego skryptu do ich generowania. Poza tym wydaje się, że działa całkiem nieźle.
Oto przykład wyliczenia z mojej bazy kodu, bez całego kodu frameworka, który implementuje makra i szablony, ale możesz zrozumieć:
Pomysł jest więc taki, że zamiast używać EHelpLocation, używasz SEHelpLocation; wszystko działa tak samo, ale otrzymujesz sprawdzanie zakresu i metodę „Format ()” na samej zmiennej wyliczeniowej. Jeśli chcesz sformatować wartość autonomiczną, możesz użyć CEnumFormatter_EHelpLocation :: FormatEnum (...).
Mam nadzieję, że to jest pomocne. Zdaję sobie sprawę, że to również nie odnosi się do pierwotnego pytania o skrypt, który faktycznie generuje drugą klasę, ale mam nadzieję, że struktura pomoże komuś próbującemu rozwiązać ten sam problem lub napisać taki skrypt.
źródło
To niewydane oprogramowanie, ale wydaje się, że BOOST_ENUM autorstwa Franka Lauba może pasować do rachunku. Podoba mi się to, że można zdefiniować wyliczenie w zakresie klasy, na co większość wyliczeń opartych na makrach zwykle nie pozwala. Znajduje się w Boost Vault pod adresem : http://www.boostpro.com/vault/index.php?action=downloadfile&filename=enum_rev4.6.zip&directory=& Nie widziałem żadnych zmian od 2006 roku, więc nie wiedzieć, jak dobrze komponuje się z nowymi wydaniami Boost. Przykład użycia znajdziesz w libs / test.
źródło
To było moje rozwiązanie z BOOST:
Aby utworzyć wyliczenie, zadeklaruj:
W przypadku konwersji:
źródło
Chcę to opublikować na wypadek, gdyby ktoś uznał to za przydatne.
W moim przypadku po prostu muszę wygenerować
ToString()
iFromString()
działać dla pojedynczego wyliczenia C ++ 11 z jednego.hpp
pliku.Napisałem skrypt w języku Python, który analizuje plik nagłówkowy zawierający elementy wyliczenia i generuje funkcje w nowym
.cpp
pliku.Możesz dodać ten skrypt w CMakeLists.txt z execute_process lub jako zdarzenie przed kompilacją w programie Visual Studio.
.cpp
Plik zostanie automatycznie wygenerowany, bez konieczności ręcznie aktualizować za każdym razem nowy element wyliczenia dodaje.gene_enum_strings.py
Przykład:
ErrorCode.hpp
Biegać
python generate_enum_strings.py ErrorCode.hpp
Wynik:
ErrorCode.cpp
źródło
Dodając jeszcze prostszą obsługę do fantastycznej odpowiedzi Jaspera Bekkersa :
Skonfiguruj raz:
Następnie do użytku:
źródło
Możesz użyć biblioteki refleksji, takiej jak Ponder . Rejestrujesz wyliczenia, a następnie konwertujesz je tam iz powrotem za pomocą interfejsu API.
źródło
Problem z odpowiedzią 0 polega na tym, że wartości binarne wyliczenia niekoniecznie zaczynają się od 0 i niekoniecznie są ciągłe.
Kiedy tego potrzebuję, zwykle:
źródło
Poniższy skrypt ruby próbuje przeanalizować nagłówki i zbudować wymagane źródła obok oryginalnych nagłówków.
Używanie wyrażeń regularnych sprawia, że ten "parser" jest dość kruchy, może nie być w stanie z wdziękiem obsłużyć określonych nagłówków.
Powiedzmy, że masz nagłówek toto / ah, zawierający definicje wyliczeń MyEnum i MyEnum2. Skrypt zbuduje:
Bardziej solidne rozwiązania to:
źródło
To właściwie jedyny sposób, w jaki można to zrobić (tablica ciągów może również działać).
Problem polega na tym, że po skompilowaniu programu w języku C wartość binarna wyliczenia jest wszystkim, co jest używane, a nazwa znika.
źródło
Oto program CLI, który napisałem, aby łatwo konwertować wyliczenia na ciągi. Jest łatwy w użyciu i zajmuje około 5 sekund, aby to zrobić (łącznie z czasem cd do katalogu zawierającego program, a następnie uruchom go, przekazując do niego plik zawierający wyliczenie).
Pobierz tutaj: http://www.mediafire.com/?nttignoozzz
Temat dyskusji na ten temat tutaj: http://cboard.cprogramming.com/projects-job-recruitment/127488-free-program-im-sharing-convertenumtostrings.html
Uruchom program z argumentem „--help”, aby uzyskać opis, jak go używać.
źródło
Nie tak dawno zrobiłem sztuczkę, aby wyliczenia były poprawnie wyświetlane w QComboBox i aby definicja reprezentacji wyliczeń i ciągów była jedną instrukcją
Teraz możesz
enumeration::enum_singleton<your_enum>::instance()
konwertować wyliczenia na ciągi. Jeśli zastąpiszkv_storage_t
goboost::bimap
, będziesz mógł również wykonać konwersję wsteczną. Wprowadzono wspólną klasę bazową dla konwertera, aby przechowywać go w obiekcie Qt, ponieważ obiekty Qt nie mogą być szablonamiPoprzedni wygląd
źródło
Jako wariant użyj prostej biblioteki> http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C
W kodzie
dodaj linie
Działa dobrze, jeśli wartości w enum nie są publikowane .
Przykładowe użycie
i wzajemnie
źródło
Oto próba automatycznego uzyskania operatorów strumieni << i >> na wyliczeniu za pomocą makra z jednym wierszem ...
Definicje:
Stosowanie:
Nie jestem pewien co do ograniczeń tego schematu ... komentarze są mile widziane!
źródło
źródło