2012-02-23 6 views
8

Considérese una macro sencilla:Usando comas dentro de una macro sin paréntesis: ¿Cómo puedo mezclar y combinar con una plantilla?

#define ECHO(x) x 

ECHO(foo(1, 2)) 

Esto produce la salida exacta se espera:

foo(1, 2) 

El ejemplo anterior funciona porque el paréntesis adyacente a la llamada de función son reconocidos por el preprocesador.

Ahora considere lo que sucede si uso una plantilla en lugar de una llamada de función:

ECHO(template<int, bool>) 

Esto provoca un error debido a que el preprocesador interpreta el template<int y los bool> como dos argumentos separados a la macro. ¡El preprocesador no reconoce <> por alcance!

¿Hay alguna forma de usar una plantilla como esta en una macro?

+0

posible duplicado de [C++ macro problema (interpretación de coma,)] (http: //desbordamiento de pila.com/questions/5348077/c-macro-problem-interpretation-of-comma) –

+1

@OliCharlesworth Ah, no encontré ese en mi búsqueda. La respuesta no parece responder a mi problema exacto, aunque proporciona algunos elementos de reflexión. Gracias. – chrisaycock

+0

Una pregunta más reciente tiene algunas respuestas excelentes: http://stackoverflow.com/questions/13842468/comma-in-cc-macro/13842784#13842784 – jjrv

Respuesta

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

Un poco doloroso, pero funciona.

Fwiw, si la sintaxis para el argumento permite () s, que no es necesario la sustitución, por ejemplo,

ECHO((a, b)) 

va a trabajar para una sola macro argumento, pero que no funciona en todos los casos (incluido el tuyo).

+2

Tenga en cuenta que tiene 'BOOST_PP_COMMA' si puede incluir' "boost/preprocessor/puntuación/comma.hpp "'. http://www.boost.org/doc/libs/1_31_0/libs/preprocessor/doc/ref/comma.html – alfC

1

si se permite el uso de Cog en su proyecto, su código se vuelve más legible:

/*[[[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]]] 

Después de ejecutar dentada sobre este archivo, obtendrá:

/*[[[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]]] 

Incluso puede mueva sus definiciones en archivos .py separados y la sección del engranaje se verá así:


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]]] 

la principal ventaja de la utilización de engranaje es que a obtener el control completo de su generación de código, completamente evitar líos ilegibles usando preprocesador impulso o cosas como eso.

la principal desventaja es que agrega una nueva dependencia de herramienta a su proyecto, también porque necesita ajustar su uso en comentarios con los marcadores de la sección de engranaje, en realidad podría ser peor que escribir el código manualmente para usos pequeños. Realmente vale la pena cuando tiene que declarar grandes enumeraciones o gran cantidad de código repetitivo inevitable

5

Una macro variadic puede ayudar:

#define ECHO(x...) x 

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

Tenga en cuenta que esto utiliza una extensión de GNU. La forma estándar (C++ 11) sería '#define ECHO (...) __VA_ARGS__'. – a3f

Cuestiones relacionadas