Se sei disposto a scrivere codice "birichino" che fa piangere altri sviluppatori, allora sì. Prova questo:
#define ENUM(name, ...) typedef enum { M_FOR_EACH(ENUM_IDENTITY, __VA_ARGS__) } name; \
char * name ## _DEBUGSTRINGS [] = { M_FOR_EACH(ENUM_STRINGIZE, __VA_ARGS__) };
#define ENUM_IDENTITY(A) A,
#define ENUM_STRINGIZE(A) #A,
ENUM(MyEnum,
foo, bar, baz, boo
)
Ovviamente hai bisogno di una macro for-each per farlo funzionare. Ecco un semplice:
#define M_NARGS(...) M_NARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define M_NARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B
#define M_FOR_EACH(ACTN, ...) M_CONC(M_FOR_EACH_, M_NARGS(__VA_ARGS__)) (ACTN, __VA_ARGS__)
#define M_FOR_EACH_0(ACTN, E) E
#define M_FOR_EACH_1(ACTN, E) ACTN(E)
#define M_FOR_EACH_2(ACTN, E, ...) ACTN(E) M_FOR_EACH_1(ACTN, __VA_ARGS__)
#define M_FOR_EACH_3(ACTN, E, ...) ACTN(E) M_FOR_EACH_2(ACTN, __VA_ARGS__)
#define M_FOR_EACH_4(ACTN, E, ...) ACTN(E) M_FOR_EACH_3(ACTN, __VA_ARGS__)
#define M_FOR_EACH_5(ACTN, E, ...) ACTN(E) M_FOR_EACH_4(ACTN, __VA_ARGS__)
#define M_FOR_EACH_6(ACTN, E, ...) ACTN(E) M_FOR_EACH_5(ACTN, __VA_ARGS__)
#define M_FOR_EACH_7(ACTN, E, ...) ACTN(E) M_FOR_EACH_6(ACTN, __VA_ARGS__)
#define M_FOR_EACH_8(ACTN, E, ...) ACTN(E) M_FOR_EACH_7(ACTN, __VA_ARGS__)
#define M_FOR_EACH_9(ACTN, E, ...) ACTN(E) M_FOR_EACH_8(ACTN, __VA_ARGS__)
#define M_FOR_EACH_10(ACTN, E, ...) ACTN(E) M_FOR_EACH_9(ACTN, __VA_ARGS__)
Dovrebbe essere ovvio come estendere quel loop di avere un limite superiore di più, ma ... le considerazioni di spazio per questa risposta. Il ciclo può essere potenzialmente lungo quanto sei disposto a copiare e incollare più iterazioni in questo bit.
Per la generazione non di debug, avere un #ifdef scegliere una versione di ENUM senza la seconda riga.
EDIT: di rubare l'inizializzatori idea designato dal teppic, ecco una versione ancora più orribile che funziona anche con i non-ordinato initialiser valori:
#define ENUM(name, ...) typedef enum { M_FOR_EACH(ENUM_ENAME, __VA_ARGS__) } name; \
char * name ## _DEBUGSTRINGS [] = { M_FOR_EACH(ENUM_ELEM, __VA_ARGS__) };
#define ENUM_ENAME(A) M_IF(M_2ITEMS(M_ID A), (M_FIRST A = M_SECOND A), (A)),
#define ENUM_ELEM(A) M_IF(M_2ITEMS(M_ID A), ([M_FIRST A] = M_STR(M_FIRST A)), ([A] = M_STR(A))),
#define M_STR(A) M_STR_(A)
#define M_STR_(A) #A
#define M_IF(P, T, E) M_CONC(M_IF_, P)(T, E)
#define M_IF_0(T, E) M_ID E
#define M_IF_1(T, E) M_ID T
#define M_2ITEMS(...) M_2I_(__VA_ARGS__, 1, 0)
#define M_2I_(_2, _1, N, ...) N
#define M_FIRST(A, ...) A
#define M_SECOND(A, B, ...) B
#define M_ID(...) __VA_ARGS__
ENUM(MyEnum,
foo, bar, baz, boo
)
ENUM(NotherEnum,
A, B, (C, 12), D, (E, 8)
)
Non posso garantire la vostra sicurezza personale, se usi questo tipo di cose nel codice che qualcun altro deve mantenere.
Per quanto ne so non c'è un modo per farlo, a meno di scrivere il tuo metodo, come hai fatto tu. –
Sfortunatamente non è possibile poiché i nomi enum non sono disponibili in una compilazione passata. – iDev
possibile duplicato di [Converti obiettivo-c typedef nella sua stringa equivalente] (http://stackoverflow.com/questions/1094984/convert-objective-c-typedef-to-its-string-equivalent). Puoi utilizzare uno dei metodi suggeriti lì. – iDev