2012-01-16 19 views
11

C'è un modo migliore per "sovraccaricare" una macro come questa? Ho bisogno di una macro che accetti vari numeri di parametri.Macro sovraccarico C

#define DEBUG_TRACE_1(p1) std::string p[] = {p1}; log _log(__FUNCTION__, p, 1) 
#define DEBUG_TRACE_2(p1, p2) std::string p[] = {p1, p2}; log _log(__FUNCTION__, p, 2) 
#define DEBUG_TRACE_3(p1, p2, p3) std::string p[] = {p1, p2, p3}; log _log(__FUNCTION__, p, 3) 
#define DEBUG_TRACE_4(p1, p2, p3, p4) std::string p[] = {p1, p2, p3, p4}; log _log(__FUNCTION__, p, 4) 
#define DEBUG_TRACE_5(p1, p2, p3, p4, p5) std::string p[] = {p1, p2, p3, p4, p5}; log _log(__FUNCTION__, p, 5) 

Chiamato come questo

DEBUG_TRACE_2("more", "params"); 
+1

C'è qualche supporto per varargs nel processore di macro C++ (non so di ANSI C), ma ogni volta Provo ad usarlo mi sembra di rischiare di provocare un'implosione dell'universo conosciuto. –

+1

Un po 'qui: http: //stackoverflow.com/questions/679979/how-to-make-a-variadic-macro-variable-number-of-arguments –

+1

'#define DEBUG_TRACE (ar, n) std :: string p [] = ar; log _log (__ FUNCTION __, p, n) ', chiama con' DEBUG_TRACE ({"more", "params"}, 2); 'era troppo semplice? –

risposta

19

Il modo più semplice per fare il vostro esempio specifico sarebbe stato con una macro variadic:

#define DEBUG_TRACE(...)          \ 
    do {              \ 
     std::string p[] = { __VA_ARGS__ };      \ 
     log _log(__FUNCTION__, p, (sizeof p)/(sizeof p[0])); \ 
    } while (0) 

Un paio di note:

  1. __VA_ARGS__ è il nome per la lista di argomenti separati da virgole forniti ai la macro
  2. Puoi scoprire quanti ce ne sono nel tuo caso usando sizeof dato che p è un array statico
  3. Sur arrotondare il codice macro in do..while è spesso considerato una buona pratica perché dà a variabili (p) un ambito di blocco in modo che gli utenti possano ancora avere una variabile con lo stesso nome al di fuori della macro e la porzione while (0) accetta piacevolmente un punto e virgola poi senza rompere una riga se le dichiarazioni

Se avete bisogno di maggiore flessibilità di questo, è possibile utilizzare un trucco molto ordinato per consentire di esplicitamente "sovraccaricare" la macro a comportarsi in modo completamente diverso con un diverso numero di parametri. Tuttavia, questo rende il codice molto più complicato e dovrebbe essere usato solo se è assolutamente necessario. Dal momento che sembra che gli argomenti variadici andranno bene per il tuo caso d'uso, ti fornirò un collegamento: http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/

+0

+1 per la nota 'do while' – tangrs

+1

Ovviamente solo un refuso ma la macro si espande semplicemente a' do {'. Anche il resto delle linee eccetto l'ultimo deve essere tagliato. – ahcox

+0

@ahcox grazie, risolto! –

14

E 'possibile utilizzare lo standard C/C++ args variadic nelle macro, almeno in gcc (EDIT: a quanto pare sono standardizzati, e MS compilatore C also has them) .

Vedere this page per alcune informazioni su come funziona.

C'è anche another question su questo sito che può essere utile per voi.

+5

I macro variabili sono stati standardizzati in C99 e C++ 11: http://en.wikipedia.org/wiki/Variadic_macro – Thomas

+2

E 'supportato anche in C++ 11: "Se c'è un' ... 'nell'identificatore- elenco nella definizione della macro, quindi gli argomenti finali, compresi i token di preprocessing della virgola di separazione, vengono uniti per formare un singolo elemento: gli argomenti della variabile. Il numero di argomenti così combinati è tale che, dopo la fusione, il numero di argomenti è uno più del numero di parametri nella definizione di macro ".." Un identificatore '__VA_ARGS__' presente nella lista di sostituzione deve essere trattato come se fosse un parametro, e gli argomenti variabili devono formare i token di preelaborazione usati per sostituirlo." –