preprocesamiento - ¿Es posible que las macros del preprocesador C contengan directivas de preprocesador?
que es include en c++ (6)
A diferencia de las plantillas, el preprocesador no es completo . Un #ifdef
dentro de una macro no es posible. Su única solución es asegurarse de llamar solo a print_max
en los tipos que tienen un _MAX
definido, por ejemplo, INT_MAX
. El compilador seguramente le dirá cuando no lo son.
Me gustaría hacer el equivalente de lo siguiente:
#define print_max(TYPE) /
# ifdef TYPE##_MAX /
printf("%lld/n", TYPE##_MAX); /
# endif
print_max(INT);
Ahora, la #ifdef
o cualquier preprocesador anidado no está permitida hasta donde puedo ver en una macro de función. ¿Algunas ideas?
Actualización: Parece que esto no es posible. Incluso un truco para comprobar en tiempo de ejecución parece inalcanzable. Entonces creo que iré con algo como:
#ifndef BLAH_MAX
# define BLAH_MAX 0
#endif
# etc... for each type I''m interested in
#define print_max(TYPE) /
if (TYPE##_MAX) /
printf("%lld/n", TYPE##_MAX);
print_max(INT);
print_max(BLAH);
El preprocesador de Boost (que funciona tanto para C como para C ++, aunque Boost en conjunto es una biblioteca de C ++) puede ayudar con este tipo de tarea. En lugar de usar un #ifdef dentro de una macro (que no está permitido), le ayuda a incluir un archivo varias veces, con diferentes macros definidas cada vez, para que el archivo pueda usar #ifdef.
El siguiente código, si se guarda en max.c, debe hacer lo que desee para cada una de las palabras enumeradas en el # Definir de MAXES en la parte superior del archivo. Sin embargo, no funcionará si alguno de los valores _MAX es coma flotante, ya que el preprocesador no puede manejar el punto flotante.
(El Boost Processor es una herramienta útil, pero no es exactamente sencillo, puede decidir si este enfoque es una mejora sobre copiar y pegar).
#define MAXES (SHRT)(INT)(LONG)(PATH)(DOESNT_EXIST)
#if !BOOST_PP_IS_ITERATING
/* This portion of the file (from here to #else) is the "main" file */
#include <values.h>
#include <stdio.h>
#include <boost/preprocessor.hpp>
/* Define a function print_maxes that iterates over the bottom portion of this
* file for each word in MAXES */
#define BOOST_PP_FILENAME_1 "max.c"
#define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MAXES)))
void print_maxes(void) {
#include BOOST_PP_ITERATE()
}
int main(int argc, char *argv[])
{
print_maxes();
}
#else
/* This portion of the file is evaluated multiple times, with
* BOOST_PP_ITERATION() resolving to a different number every time */
/* Use BOOST_PP_ITERATION() to look up the current word in MAXES */
#define CURRENT BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(), MAXES)
#define CURRENT_MAX BOOST_PP_CAT(CURRENT, _MAX)
#if CURRENT_MAX
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is %lld/n", (long long) CURRENT_MAX);
#else
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is undefined/n");
#endif
#undef CURRENT
#undef CURRENT_MAX
#endif
La única solución que tengo es hacer trampa: producir una lista de tipos que tengan un _XXX_MAX como un conjunto de definiciones, y luego usar eso. No sé cómo producir la lista de forma automática en el preprocesador, así que no lo intento. La suposición es que la lista no es demasiado larga y no se mantendrá demasiado intensa.
#define PRINT_MAX(type) printf("%lld/n", _TYPE##_MAX);
#define HAVE_MAX(type) _TYPE##_MAX // not sure if this works
/* a repetitious block of code that I cannot factor out - this is the cheat */
#ifdef HAVE_MAX(INT)
#define PRINT_INT_MAX PRINT_MAX(INT)
#endif
#ifdef HAVE_MAX(LONG)
#define PRINT_LONG_MAX PRINT_MAX(LONG)
#endif
/* end of cheat */
#define print_max(type) PRINT_##TYPE##_MAX
Lo he intentado antes. El problema es que #
ya está reservado para stringize un parámetro de macro. No se analiza como un token de preprocesador como el de #
define.
No creo que sea un caso de que el operador ## no esté permitido en un #ifdef. Intenté esto:
#define _print_max(TYPE) /
#ifdef TYPE /
printf("%lld/n", _TYPE); /
#endif
#define print_max(TYPE) _print_max(MAX##_TYPE)
void main()
{
print_max(INT)
}
y todavía no funcionó (no le gustó #ifdef TYPE). El problema es que #ifdef solo aceptará # símbolos definidos, no #definir argumentos. Esas son dos cosas diferentes.
No hay una manera fácil de hacer esto. Lo más cerca que puede venir es #definir una gran cantidad de macros IFDEF tales como:
#undef IFDEF_INT_MAX
#ifdef INT_MAX
#define IFDEF_INT_MAX(X) X
#else
#define IFDEF_INT_MAX(X)
#endif
#undef IFDEF_BLAH_MAX
#ifdef BLAH_MAX
#define IFDEF_BLAH_MAX(X) X
#else
#define IFDEF_BLAH_MAX(X)
#endif
:
ya que necesita muchos de ellos (y pueden ser útiles en varios lugares), tiene mucho sentido incluirlos en su propio archivo de cabecera ''ifdefs.h'', que puede incluir cuando lo necesite. Incluso puedes escribir un script que regenere ifdef.h de una lista de ''macros de interés''
Entonces, su código se convierte
#include "ifdefs.h"
#define print_max(TYPE) /
IFDEF_##TYPE##_MAX( printf("%lld/n", TYPE##_MAX); )
print_max(INT);
print_max(BLAH);