Macro variadique et virgule de fin

J’essaie de faire l’orientation object en C et je veux une macro sucre syntaxique

object->vtable->method(object, arg1, arg2) 

dans

 send(object, method, arg1, arg2) 

Malheureusement, lorsqu’une méthode ne prend pas d’argument, le problème de la virgule finale se pose.

 send(object, method) 

donne

 object->vtable->method(object, ) 

Existe-t-il un moyen portable (sans ##__VA_ARGS__ ou Visual Studio) de le faire?

J’en ai trouvé une mais j’ai besoin d’échanger l’object et la méthode

 #define FIRST_ARG_(N, ...) N #define FIRST_ARG(args) FIRST_ARG_(args) #define send(msg, ...) \ FIRST_ARG(__VA_ARGS__)->vtable->msg(__VA_ARGS__) 

les permis

 send(method, object) send(method, object, arg1, arg2) 

modifier

Avec l’aide de deux bonnes réponses ci-dessous, je vais le faire avec ces macros. Cela fonctionne jusqu’à 16 arguments mais peut facilement être étendu

 #define SEND_NO_ARG(obj, msg) obj->vtable->msg(obj) #define SEND_ARG(obj, msg, ...) obj->vtable->msg(obj, __VA_ARGS__) #define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \ arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, \ arg16, arg17, arg18, ...) arg18 #define SEND_MACRO_CHOOSER(...) \ GET_18TH_ARG(__VA_ARGS__, \ SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \ SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \ SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \ SEND_NO_ARG, ) #define SEND(...) SEND_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__) 

Dans cette réponse, il est expliqué une technique qui devrait vous permettre de compter le nombre de parameters et d’utiliser object et method comme les deux premiers arguments.

Réponse courte, oui, c’est possible de manière portable.

Réponse longue: c’est compliqué et vous ne voulez probablement pas l’implémenter vous-même. Il existe des moyens de compter les arguments qu’une macro reçoit, puis d’agir en fonction de ce nombre. P99 implémente une série de macros qui peuvent vous aider à atteindre cet objective. Si vous souhaitez implémenter deux macros de base, send_2 et send_more , vous pouvez alors implémenter send tant que

 #define send(...) \ P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \ (send_2(__VA_ARGS__)) \ (send_more(__VA_ARGS__)) 

Techniquement, ces constructions dans P99 ont une ressortingction selon laquelle elles ne peuvent pas gérer plus de 150 arguments (ou plus) à send .

BTW, vous savez que probablement, appeler un send macro n’est pas vraiment une bonne idée. Les gens préfèrent généralement que les macros soient en majuscule. La plupart du temps, il est également judicieux d’avoir un préfixe de nom propre à votre bibliothèque / package, tel que AC245_SEND .