Después de hablar de las macros hace unos días, me he dedicado a investigar algo más sobre cómo funciona el preprocesador de C/C++. Está muy limitado, pero tiene algunas posibilidades.
Usando #if/#endif es posible seleccionar parte de código, pero no podemos usar #if/#endif dentro de una macro. Es decir algo como esto no funciona
#define SELECCIONA(a,b,c) #if a \
b \
#else \
c \
#endif
El motivo es que el preprocesador es muy tonto y sus comandos (que empiezan por #) sólo son reconocidos a principio de línea. Debido a que el \ a final de línea significa que se sigue en la siguiente línea como si fuera esta, la macro anterior sería equivalente a
#define SELECCIONA(a,b,c) #if a b #else c #endif
Por lo que ni el #if ni el #else ni el #endif son reconocidos como comandos de preprocesador.
La solución es algo enrevesada, pero funciona y es usada en boost::preprocesor. Se basa en el concatenador de tokens. Es un operador especial (no es un comando) del preprocesador. Se escribe ##. El resultado de esta concatenación es agrupar dos identificadores en uno.
#define CONCATENA(a,b) a ## b
CONCATENA(hola, adios) //Equivalente a escribir holaadios
Debido a que el preprocesador vuelve a expandir el resultado de sus macros, es fácil usar el siguiente truco para la selección.
#define IF_TRUE(t,e) t
#define IF_FALSE(t,e) e
#define IF(c,t,e) IF_##c (t, e)
IF(TRUE, bien, mal) //Se expande a IF_TRUE(bien,mal) y se vuelve a expandir a bien
Ahora podemos combinar este truco con la técnica explicada hace unos días para crear código opcionalmente.
0 comentarios:
Publicar un comentario