2012-02-23 13 views
8

consideri una semplice macro:Uso di virgole all'interno di una macro senza parentesi: come posso mescolare e abbinare un modello?

#define ECHO(x) x 

ECHO(foo(1, 2)) 

Questo produce l'uscita esatta ci aspettiamo:

foo(1, 2) 

L'esempio precedente funziona perché la parentesi adiacente alla chiamata di funzione sono riconosciuti dal preprocessore.

Ora consideriamo cosa succede se uso un modello invece di una chiamata di funzione:

ECHO(template<int, bool>) 

Questo provoca un errore perché il preprocessore interpreta il template<int ei bool> come due argomenti separati alla macro. Il preprocessore non riconosce <> per l'ambito!

Esiste comunque un modello come questo in una macro?

+0

possibile duplicato del [C++ macro problema (interpretazione del comma,)] (http: // StackOverflow.it/questions/5348077/c-macro-problema-interpretazione-di-virgola) –

+1

@OliCharlesworth Ah, non l'ho trovato nella mia ricerca. La risposta non sembra rispondere al mio esatto problema, sebbene fornisca qualche spunto di riflessione. Grazie. – chrisaycock

+0

Una domanda più recente ha alcune risposte eccellenti: http://stackoverflow.com/questions/13842468/comma-in-cc-macro/13842784#13842784 – jjrv

risposta

11
#define COMMA , 
ECHO(template<int COMMA bool>) 

Un po 'doloroso, ma funziona.

FWIW, se la sintassi per l'argomento permette () s, non è necessario la sostituzione, ad esempio,

ECHO((a, b)) 

lavorerà per una singola macro argomento, ma che non funziona in tutti i casi (incluso il tuo).

+2

Nota che hai 'BOOST_PP_COMMA' se puoi includere' "boost/preprocessore/punteggiatura/comma.hpp "'. http://www.boost.org/doc/libs/1_31_0/libs/preprocessor/doc/ref/comma.html – alfC

1

se si consente l'utilizzo di Cog nel progetto, il codice diventa più leggibile:

/*[[[cog 
# definitions ---- 
import cog 

def AddDeclaration(templateArg , restOfDeclaration): 
    cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration)) 

# generation --- 
types = ['bool' , 'std::string'] 
names = ['Foo' , 'Bar'] 
for index in range(len(names)): 
    AddDeclaration('template<int, %s>' % types[index] , names[index]) 
]]]*/ 
//[[[end]]] 

Dopo aver eseguito cremagliera su questo file, si otterrà:

/*[[[cog 
# definitions ---- 
import cog 

def AddDeclaration(templateArg , restOfDeclaration): 
    cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration)) 

# generation --- 
types = ['bool' , 'std::string'] 
names = ['Foo' , 'Bar'] 
for index in range(len(names)): 
    AddDeclaration('template<int, %s>' % types[index] , names[index]) 
]]]*/ 
template<int, bool> struct Foo; <---------------- generated by Cog!! 
template<int, std::string> struct Bar; 
//[[[end]]] 

È anche possibile sposta le tue definizioni in file .py separati e la sezione cog sarà simile a:


declarations.py

import cog 

def AddDeclaration(templateArg , restOfDeclaration): 
    cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration)) 

my.h

/*[[[cog 
# definitions ---- 
import declarations 
# generation --- 
types = ['bool' , 'std::string'] 
names = ['Foo' , 'Bar'] 
for index in range(len(names)): 
    AddDeclaration('template<int, %s>' % types[index] , names[index]) 
]]]*/ 
template<int, bool> struct Foo; 
template<int, std::string> struct Bar; 
//[[[end]]] 

il principale vantaggio di utilizzare COG è che si guadagna il controllo completo della tua generazione del codice, completamente evitare pasticci illeggibili utilizzando preprocessore spinta o roba come quello.

lo svantaggio principale è che si aggiunge una nuova dipendenza strumento al progetto, anche perché è necessario avvolgere il suo utilizzo nei commenti con i marcatori di sezione cog, potrebbe effettivamente essere peggio di scrivere manualmente il codice per piccoli utilizzi. Si ripaga quando è necessario dichiarare grandi enumerazioni o sacco di codice inevitabile boilerplate

5

Una macro variadic può aiutare:

#define ECHO(x...) x 

ECHO(foo(1, 2)) 
ECHO(template<int, bool>) 
+2

Si noti che questo utilizza un'estensione GNU. Il modo standard (C++ 11) sarebbe '#define ECHO (...) __VA_ARGS__'. – a3f

Problemi correlati