2010-09-22 14 views
6

Dopo aver letto VA_NARGincollare Token C

ho cercato di implementare la funzione sovraccarico seconda del numero di argomenti C utilizzo di macro. Ora il problema è:

void hello1(char *s) { ... } 
void hello2(char *s, char *t) { ... } 
// PP_NARG(...)   macro returns number of arguments :ref to link above 
// does not work 
#define hello(...)   hello ## PP_NARG(__VA_ARGS__) 

int main(void) 
{ 
    hello("hi"); // call hello1("hi"); 
    hello("foo","bar"); // call hello2("foo","bar"); 
    return 0; 
} 

Ho letto this da C-faq. Ma ancora non poteva farlo funzionare ...

risposta

4

Questo è a causa delle regole di valutazione per le macro. Dovresti definire una sorta di macro helper che riceve il numero come token:

#define HELLO_1(N, ...)   hello ## N 
#define HELLO_0(N, ...)   HELLO_1(N, __VARGS__) 
#define HELLO(...)   HELLO_0(PP_NARG(__VA_ARGS__), __VARGS__) 

o così. Puoi anche dare un'occhiata alla versione preliminare della documentazione di P99. Ciò fornirà strumenti macro più comodi per farlo direttamente.

+0

"o così" Infatti. Ha bisogno di un ulteriore livello di riferimento per farlo funzionare. –

+0

@ John: si, grazie. Uso sempre la mia versione di una macro incolla per questo, quindi ho difficoltà a ricordare quanti livelli di riferimento indiretto sono necessari se si ha solo '##'. Ho adattato la mia risposta di conseguenza. –

+0

Grazie che funziona. ma CIAO ("foo") dona ciao1; non ciao1 ("pippo"). Ma mi viene l'idea ... – Nyan

0

Non ho un compilatore C99 a disposizione per controllare, ma questo dovrebbe funzionare:

#define helloN(N, ...) hello ## N (__VA_ARGS__) 
#define hello(...) helloN(PP_NARG(__VA_ARGS__), __VA_ARGS__) 
4

Che PP_NARG è un pezzo piuttosto impressionante di follia!

Seguendo il glue esempio nello standard C99 (6.10.3.5, esempio 4), la seguente produce i risultati desiderati:

#define glue(a, b) a ## b 
#define xglue(a, b) glue(a, b) 

#define hello(...) xglue(hello, PP_NARG(__VA_ARGS__))(__VA_ARGS__)