2013-08-29 12 views
5

Ho la seguente macro:C++ macro di pre-elaborazione con 2 argomenti

#define LOG(level,text) 

voglio definire macro che include sia il livello e il testo:

#define MY_LOG_MESSAGE LEVEL1,"This is my log" 

così quest'ultimo posso correre:

LOG(MY_LOG_MESSAGE); 

errore di preelaborazione problemi di gcc:

error: macro "LOG" requires 2 arguments, but only 1 given

Qualche idea?

+0

Cosa significa 'LOG' espandersi? – trojanfoe

+0

@trojanfoe Fallisce il preprocesso – dimba

+0

Se si tratta in realtà della registrazione e non solo di un esempio, suggerirei seriamente di utilizzare una libreria di registrazione appropriata, ad es. [Boost.Log] (http://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/index.html), invece di far girare il tuo. Soprattutto se è basato sul preprocessore. –

risposta

2

Se si utilizza un definiscono per ogni messaggio di log in ogni modo, forse fare in questo modo:

#define LOG_MY_MESSAGE LOG(LEVEL1, "This is my log")

An d utilizzare nel codice semplicemente come

LOG_MY_MESSAGE

+0

Probabilmente questo potrebbe funzionare, ma ho diversi macro come LOG(). Nella tua soluzione avrò bisogno di definire LOG_MY_MESSAGE per macro LOG. – dimba

+0

@dimba No, non è possibile utilizzare le macro LOG() come parametro. Quindi utilizzare '#define LOG_MY_MESSAGE (logger) logger (LEVEL1," Questo è il mio log ")' Nel tuo codice puoi usarlo scrivendo 'LOG_MY_MESSAGE (LOG)' – sebi

+0

Ci sono diverse soluzioni simili, ma tu sei stato il primo. – dimba

0

sì, definire LOG come questo:

#define LOG(text) 

poi LOG ricevono solo 1 parametro e si può utilizzare con il vostro messaggio

LOG(MY_LOG_MESSAGE); 
+0

Non riesco a ridefinire LOG() - non è il mio codice :( – dimba

+0

@dimba Sì, è possibile, basta sostituirlo – trojanfoe

0

Il preprocessore va dall'inizio di ciascun file alla fine di esso, immediatamente sostituendo qualsiasi macro con la sostituzione lista di token. Nel tuo caso, LOG viene sostituito per primo, prima che lo MY_LOG_MESSAGE venga sostituito con 2 argomenti, quindi l'errore.

0

MY_LOG_MESSAGE verranno trattati come un argomento dal preprocessore, perché è una direttiva del preprocessore. LEVEL1,"This is my log" è contenuto all'interno di MY_LOG_MESSAGE e viene trattato come un singolo argomento del preprocessore quando utilizzato in altre direttive del preprocessore.

per chiamare le funzioni semplici come

void DoLogging(Level level, const std::string& msg) 

la macro saranno trattati come ci si aspetta. Quindi, DoLogging(MY_LOG_MESSAGE) funzionerà. Si espanderà qui, perché è not utilizzato come argomento di un'altra direttiva preprocessore, ma all'interno di una funzione real. Che cosa potrebbe aiutare è qualcosa di simile:

#define MY_LOG_MESSAGE LOG(LEVEL1, "My message") 

Furhtermore, se ci sono LOG multipla() - macro, come lei ha sottolineato, basta usare come parametro di voi MY_LOG_MESSAGE, in questo modo:

#define MY_LOG_MESSAGE(logger) logger(LEVEL1, "My message") 

Nel tuo codice chiamalo semplicemente MY_LOG_MESSAGE(LOG)

1

Questo non può funzionare in questo modo. Per il preprocessore stai dando un solo argomento alla MACRO LOG quando ne ha bisogno due.

È possibile risolverlo facendo qualcosa di un po 'più facile:

#define MY_LOG_MESSAGE LOG(LEVEL1, "This is my log") 

e usarlo come:

MY_LOG_MESSAGE 

Spiegazione:

Nel caso:

#define LOG(level,text) 

#define MY_LOG_MESSAGE LEVEL1,"This is my log" 

LOG(MY_LOG_MESSAGE); 

Il preprocessore non sostituirà la macro MY_LOG_MESSAGE quando vedrà la chiamata a LOG, la passerà come argomento (come una funzione).

E 'solo dopo che, quando il preprocessore sostituirà il LOG macro che sarà una nuova scansione del sostituzione-list per vedere se ci sono più macro per elaborare.

dalla norma:

16.3.1 Argument substitution [cpp.subst]

  1. After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.

Si dice qui che le macro passato come argomento di un'altra macro sono espansi dopo che gli argomenti per l'invocazione di una funzione di macro-come sono stati identificati.

Poi si può anche forzare preprocessore per espandere le macro:

#define LOG(level, text) whatever 
#define MY_LOG_MESSAGE LEVEL1,"This is my log" 

#define LOG_LVL1(args) LOG(args) 
//    ^^^^  ^^^^ 
//   Pass a macro Will be expanded by the preprocessor here 
//       And LOG will receive the correct number of arguments 
LOG_LVL1(MY_LOG_MESSAGE) 
2

Devi convincere il preprocesor per espandere la macro MY_LOG_MESSAGE prima che tenta di espandersi LOG(). Questo can be done utilizzando una semplice macro aiutante:

#define LOG1(x) LOG(x) 

LOG1(MY_LOG_MESSAGE); 

Gli argomenti dati ai LOG1() sono espansi in esso del corpo, portando ad una chiamata valida per LOG().

2

Questo è molto simile a sth's answer, ma consente di utilizzare uno o due parametri:

#define LOG_(level,text) implementation 
#define LOG(...) LOG_(__VA_ARGS__) 

#define MY_LOG_MESSAGE LEVEL1,"This is my log" 

LOG(MY_LOG_MESSAGE); 
LOG(LEVEL2, "Another log"); 

Il punto è che LOG provoca il parametro da espandere prima di chiamare LOG_, dando in tal modo due parametri in entrambi i casi .

0
#define ELOG(message) log(LEVEL_ERR,message) 
#define WLOG(message) log(LEVEL_WARN,message) 

in modo che si può utilizzare come

ELOG("This is error msg") o WLOG("Warning msg")

a patto di avere una funzione

void log(int loglevel,char* msg)

Problemi correlati