2010-09-22 61 views
6

Après avoir lu VA_NARGcoller Token en C

j'ai essayé de mettre en œuvre la surcharge de fonctions en fonction du nombre d'arguments dans C en utilisant des macros. Maintenant, le problème est:

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

J'ai lu this de C-faq. Mais ne pouvait toujours pas faire fonctionner ...

Répondre

4

Ceci est en raison des règles d'évaluation des macros. Vous devez définir une sorte de macro auxiliaire qui reçoit le numéro sous forme de jeton:

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

ou plus. Vous pouvez également jeter un coup d'oeil dans la pré-version de la documentation de P99. Cela vous fournira des outils macro plus confortables pour le faire directement.

+0

"ou" donc en effet. Il a besoin d'un autre niveau d'indirection pour le faire fonctionner. –

+0

@John: oui, merci. J'utilise toujours ma propre version d'une macro de collage pour cela, donc j'ai du mal à me rappeler combien de niveaux d'indirection vous avez besoin si vous avez juste '##'. J'ai adapté ma réponse en conséquence. –

+0

Merci cela fonctionne. mais BONJOUR ("foo") donne bonjour1; pas hello1 ("foo"). Mais j'ai l'idée ... – Nyan

0

Je n'ai pas un compilateur C99 disponible pour vérifier, mais cela devrait fonctionner:

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

Que PP_NARG est un morceau plutôt impressionnant de folie!

Après la glue exemple dans la norme C99 (6.10.3.5, exemple 4), ce qui suit donne les résultats souhaités:

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

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